it-swarm.com.de

Was ist schneller, eine große Abfrage oder viele kleine Abfragen?

Ich habe für verschiedene Unternehmen gearbeitet und festgestellt, dass einige von ihnen Ansichten bevorzugen, die sich mit all ihren "Verwandten" an einen Tisch setzen. In der Anwendung müssen wir jedoch manchmal nur eine Spalte verwenden.

Wäre es also schneller, einfach eine Auswahl zu treffen und sie dann im Systemcode zu "verbinden"?

Das System kann PHP, Java, ASP sein, jede Sprache, die eine Verbindung zur Datenbank herstellt.

Die Frage ist also, was von einer Serverseite (PHP, Java, Asp, Ruby, Python ...) zur Datenbank schneller geht. Führen Sie eine Abfrage aus, die alles erhält, was wir benötigen, oder gehen Sie von der Serverseite zur Datenbank und führen Sie eine aus Abfrage, die jeweils nur die Spalten aus einer Tabelle abruft?

76
sudo.ie

Was Ihre Frage beantworten würde, ist das Thema JOIN DECOMPOSITION.

Nach Seite 209 des Buches

High Performance MySQL

Sie können einen Join zerlegen, indem Sie mehrere Abfragen mit einer einzelnen Tabelle anstelle eines mehrteiligen Joins ausführen und dann den Join in der Anwendung ausführen. Zum Beispiel anstelle dieser einzelnen Abfrage:

SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';

Sie können folgende Abfragen ausführen:

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

Warum um alles in der Welt würdest du das tun? Auf den ersten Blick sieht es verschwenderisch aus, weil Sie die Anzahl der Abfragen erhöht haben, ohne eine Gegenleistung zu erhalten. Eine solche Umstrukturierung kann jedoch tatsächlich erhebliche Leistungsvorteile bringen:

  • Caching kann effizienter sein. Viele Anwendungen speichern "Objekte" zwischen, die direkt Tabellen zugeordnet sind. In diesem Beispiel überspringt die Anwendung die erste Abfrage, wenn das Objekt mit dem Tag mysql bereits zwischengespeichert ist. Wenn Sie Beiträge mit der ID 123, 567 oder 908 im Cache finden, können Sie diese aus der Liste IN() entfernen. Der Abfragecache kann ebenfalls von dieser Strategie profitieren. Wenn sich nur eine der Tabellen häufig ändert, kann durch Zerlegen eines Joins die Anzahl der Cache-Ungültigmachungen verringert werden.
  • Das individuelle Ausführen der Abfragen kann manchmal die Sperrenkonflikte verringern
  • Durch Verknüpfungen in der Anwendung wird das Skalieren der Datenbank durch Platzieren von Tabellen auf verschiedenen Servern vereinfacht.
  • Die Abfragen selbst können effizienter sein. In diesem Beispiel kann MySQL mithilfe einer IN() -Liste anstelle eines Joins Zeilen-IDs sortieren und Zeilen optimaler abrufen, als dies mit einem Join möglich wäre.
  • Sie können redundante Zeilenzugriffe reduzieren. Wenn Sie einen Join in der Anwendung ausführen, müssen Sie jede Zeile nur einmal abrufen, während ein Join in der Abfrage im Wesentlichen eine Denormalisierung darstellt, die möglicherweise wiederholt auf dieselben Daten zugreift. Aus dem gleichen Grund kann eine solche Umstrukturierung auch den gesamten Netzwerkverkehr und die Speichernutzung verringern.
  • Bis zu einem gewissen Grad können Sie diese Technik als manuelles Implementieren eines Hash-Joins anstelle des Algorithmus für verschachtelte Schleifen betrachten, den MySQL zum Ausführen eines Joins verwendet. Ein Hash-Join ist möglicherweise effizienter.

Infolgedessen können Verknüpfungen in der Anwendung effizienter ausgeführt werden, wenn Sie viele Daten aus früheren Abfragen zwischenspeichern und wiederverwenden, Daten auf mehrere Server verteilen, Verknüpfungen durch IN() -Listen ersetzen oder eine Verknüpfung verweist mehrmals an dieselbe Tabelle.

ÜBERWACHUNG

Ich mag den ersten Aufzählungspunkt, weil InnoDB ein wenig hartnäckig ist, wenn es den Abfrage-Cache überprüft.

Was den letzten Aufzählungspunkt betrifft, habe ich am 11. März 2013 einen Beitrag geschrieben ( Gibt es einen Ausführungsunterschied zwischen einer JOIN-Bedingung und einer WHERE-Bedingung? ), der den verschachtelten Schleifenalgorithmus beschreibt. Nachdem Sie es gelesen haben, werden Sie sehen, wie gut die Join-Zerlegung sein kann.

Wie bei allen anderen Punkten aus dem Buch suchen die Entwickler wirklich nach Leistung als Endergebnis. Einige verlassen sich auf externe Mittel (außerhalb der Anwendung), um die Leistung zu verbessern, z. B. eine schnelle Festplatte zu verwenden, mehr CPUs/Kerne zu erhalten, die Speicher-Engine zu optimieren und die Konfigurationsdatei zu optimieren. Andere schnallen sich an und schreiben besseren Code. Einige greifen möglicherweise auf die Codierung der gesamten Business Intelligence in gespeicherten Prozeduren zurück, wenden jedoch keine Join-Zerlegung an (siehe Was sind die Argumente gegen oder für das Einfügen von Anwendungslogik in die Datenbankebene? zusammen mit den anderen Posts). Es hängt alles von der Kultur und Toleranz jedes Entwickler-Shops ab.

Einige sind möglicherweise mit der Leistung zufrieden und berühren den Code nicht mehr. Andere wissen einfach nicht, dass es große Vorteile gibt, die man nutzen kann, wenn man versucht, sich der Komposition anzuschließen.

Für diejenigen Entwickler, die bereit sind ...

VERSUCHE ES !!!

73
RolandoMySQLDBA

In Postgres (und wahrscheinlich jedem RDBMS in ähnlichem Ausmaß, MySQL in geringerem Ausmaß) sind fast weniger Abfragen immer viel schneller.

Der Aufwand für das Parsen und Planen mehrerer Abfragen ist in den meisten Fällen bereits größer als jeder mögliche Gewinn.

Ganz zu schweigen von zusätzlicher Arbeit im Client, bei der die Ergebnisse kombiniert werden, was normalerweise viel langsamer ist. Ein RDBMS ist auf diese Art von Aufgaben spezialisiert und Operationen basieren auf ursprünglichen Datentypen. Kein Casting nach text und zurück für Zwischenergebnisse oder Transformation in native Client-Typen, was sogar zu weniger korrekten (oder falschen!) Ergebnissen führen kann. Denken Sie an Gleitkommazahlen ...

Sie übertragen auch mehr Daten zwischen DB-Server und Client. Dies kann für eine Hand voller Werte vernachlässigbar sein oder einen großen Unterschied machen.

Wenn mehrere Abfragen mehrere Roundtrips zum Datenbankserver bedeuten, erfassen Sie auch das Mehrfache der Netzwerklatenz und des Transaktionsaufwands, möglicherweise sogar des Verbindungsaufwands. Großer, großer Verlust.

Abhängig von Ihrem Setup kann die Netzwerklatenz allein um Größenordnungen länger dauern als alle anderen.

Verwandte Frage zu SO:

Möglicherweise gibt es einen Wendepunkt für sehr groß, lang laufende Abfragen, da Transaktionen unterwegs Sperren für DB-Zeilen sammeln. Sehr große Abfragen können über einen längeren Zeitraum viele Sperren enthalten, was zu Reibungen mit gleichzeitigen Abfragen führen kann.

29