Keine der beiden vorgeschlagenen Lösungen ist wahrscheinlich optimal, ABER Lösung 1 ist UNVORHERSAGBAR und daher INHABER FEHLERHAFT!
Eines der ersten Dinge, die Sie beim Umgang mit großen Datenbanken lernen, ist, dass „der beste Weg“, eine Abfrage durchzuführen, oft von Faktoren (als Metadaten bezeichnet) innerhalb der Datenbank abhängt:
- Wie viele Zeilen gibt es.
- Wie viele Tabellen Sie abfragen.
- Die Größe jeder Zeile.
Aus diesem Grund ist es unwahrscheinlich, dass es eine Patentlösung für Ihr Problem gibt. Ihre Datenbank ist nicht die gleiche wie meine Datenbank, Sie müssen verschiedene Optimierungen vergleichen, wenn Sie die beste verfügbare Leistung benötigen.
Sie werden wahrscheinlich feststellen, dass korrekte Indizes anwenden und erstellen (und das Verständnis der nativen Implementierung von Indizes in MySQL) in Ihrer Datenbank tut viel mehr für Sie.
Es gibt einige goldene Regeln bei Abfragen, die selten gebrochen werden sollten:
- Machen Sie sie nicht in Schleifenstrukturen . So verlockend es oft auch sein mag, der Aufwand für das Erstellen einer Verbindung, das Ausführen einer Abfrage und das Erhalten einer Antwort ist hoch.
- Vermeiden Sie
SELECT *
sofern nicht erforderlich . Wenn Sie mehr Spalten auswählen, erhöht sich der Overhead Ihrer SQL-Operationen erheblich. - Kenne deine Indizes . Verwenden Sie das
EXPLAIN
Funktion, damit Sie sehen können, welche Indizes verwendet werden, Ihre Abfragen optimieren, um verfügbare zu verwenden, und neue erstellen können.
Aus diesem Grund würde ich mich für die zweite Abfrage entscheiden (durch Ersetzen von SELECT *
mit nur den gewünschten Spalten), aber Es gibt wahrscheinlich bessere Möglichkeiten, die Abfrage zu strukturieren, wenn Sie Zeit zum Optimieren haben.
Geschwindigkeit sollte jedoch NICHT Seien Sie dabei Ihre einzige Überlegung, es gibt einen GROSSEN Grund, Vorschlag eins nicht zu verwenden:
VORHERSEHBARKEIT:Warum Lesesperren eine gute Sache sind
Eine der anderen Antworten deutet darauf hin, dass es schlecht ist, die Tabelle über einen längeren Zeitraum zu sperren, und dass die Lösung mit mehreren Abfragen daher gut ist.
Ich würde argumentieren, dass dies nicht weiter von der Wahrheit entfernt sein könnte . Tatsächlich würde ich argumentieren, dass in vielen Fällen die Vorhersagbarkeit des Ausführens eines einzigen sperrenden SELECT
Abfrage ist ein größeres Argument für die Ausführung dieser Abfrage als die Optimierungs- und Geschwindigkeitsvorteile.
Zunächst einmal, wenn wir ein SELECT
ausführen (schreibgeschützte) Abfrage auf einer MyISAM- oder InnoDB-Datenbank (Standardsysteme für MySQL), was passiert ist, dass die Tabelle lesegesperrt ist. Dies verhindert, dass irgendwelche WRITE-Operationen auf der Tabelle ausgeführt werden, bis die Lesesperre aufgegeben wird (entweder unser SELECT
Abfrage abgeschlossen oder schlägt fehl). Andere SELECT
Abfragen sind nicht betroffen. Wenn Sie also eine Multithread-Anwendung ausführen, funktionieren sie weiterhin.
Diese Verzögerung ist eine gute Sache. Warum, fragen Sie sich vielleicht? Relationale Datenintegrität.
Nehmen wir ein Beispiel:Wir führen eine Operation durch, um eine Liste von Gegenständen zu erhalten, die sich derzeit im Inventar einer Gruppe von Benutzern eines Spiels befinden, also führen wir diese Verknüpfung durch:
SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;
Was passiert, wenn ein Benutzer während dieses Abfragevorgangs einen Artikel an einen anderen Benutzer tauscht? Mit dieser Abfrage sehen wir den Spielstatus, wie er war, als wir die Abfrage gestartet haben:Der Gegenstand existiert einmal, im Inventar des Benutzers, der ihn hatte, bevor wir die Abfrage ausgeführt haben.
Aber was passiert, wenn wir es in einer Schleife laufen lassen?
Je nachdem, ob der Benutzer es vor oder nach dem Lesen seiner Daten gehandelt hat und in welcher Reihenfolge wir die Inventare der beiden Spieler lesen, gibt es vier Möglichkeiten:
- Der Gegenstand könnte im Inventar des ersten Benutzers angezeigt werden (Benutzer B scannen -> Benutzer A scannen -> Gegenstand gehandelt ODER Benutzer B scannen -> Benutzer A scannen -> Gegenstand gehandelt).
- Der Gegenstand könnte im Inventar des zweiten Benutzers angezeigt werden (Getauschter Gegenstand -> Benutzer A scannen -> Benutzer B scannen ODER Gegenstand gehandelt -> Benutzer B scannen -> Benutzer A scannen).
- Der Artikel könnte in beidem angezeigt werden Inventare (Benutzer A scannen -> Artikel gehandelt -> Benutzer B scannen).
- Der Artikel konnte in beidem nicht angezeigt werden des Inventars des Benutzers (Benutzer B scannen -> Artikel gehandelt -> Benutzer A scannen).
Das bedeutet, dass wir nicht in der Lage wären, die Ergebnisse der Abfrage vorherzusagen oder die relationale Integrität sicherzustellen .
Wenn Sie vorhaben, dem Typen mit der Artikel-ID 1000000 am Dienstag um Mitternacht 5.000 $ zu geben, hoffe ich, dass Sie 10.000 $ zur Hand haben. Wenn Ihr Programm darauf angewiesen ist, dass eindeutige Elemente beim Erstellen von Schnappschüssen eindeutig sind, werden Sie möglicherweise mit dieser Art von Abfrage eine Ausnahme auslösen.
Das Sperren ist gut, weil es die Vorhersagbarkeit erhöht und schützt die Integrität der Ergebnisse.
Hinweis:Sie können das Sperren einer Schleife mit einer Transaktion erzwingen , aber es wird immer noch langsamer sein.
Oh, und schließlich, VERWENDEN SIE VORBEREITETE AUSSAGEN!
Das sollten Sie nie tun haben eine Anweisung, die so aussieht:
mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);
mysqli
hat Unterstützung für vorbereitete Anweisungen
. Lesen Sie mehr über sie und verwenden Sie sie, sie werden Ihnen helfen, etwas Schreckliches zu vermeiden, das Ihrer Datenbank passiert
.