MyISAM-Leistung: Join Decomposition


7

In High Performance MySQL auf Seite 159 geht es darum, komplexe Abfragen in einfache aufzuteilen:

Konvertieren

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';

Zu

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);

Und sozusagen den eigentlichen Beitritt zu Ihrer Bewerbung.

Meine Frage ist, ob dies immer noch eine so gute Idee ist, wenn die letzte Abfrage eine where-Klausel mit einigen tausend IDs enthält, mit denen sie übereinstimmen muss (die eigentliche Tabelle selbst enthält ungefähr 500.000 Einträge).

Was ich meine ist, wird es eine große Strafe für eine Anfrage wie geben

SELECT * FROM post WHERE post.id in (123,456,567, ... <a few thousand IDs here> ... ,9098,8904);

anstelle der obigen join-Anweisung? Wäre es hilfreich, diese Logik auf gespeicherte Prozeduren in der Datenbank zu verschieben (unter Berücksichtigung der Tatsache, wie schlecht gespeicherte Prozeduren in MySQL implementiert sind)?


@Bubbles Sie sollten wahrscheinlich die Datenbank neu gestalten, damit Sie keine INKlausel mit ein paar tausend IDs ausführen müssen
Patrick

Wie? Ich muss Datensätze basierend auf einer berechneten Entfernung und übereinstimmenden Tags abrufen, sortiert nach Straßennamen
Dexter

@Bubbles die postTabelle, ist dieser Beitrag wie in der Adresse? Wenn ja, könnten Sie eine Abfrage basierend auf der Postleitzahl oder nach Stadt ausführen
Patrick

Nein, der Posttisch war nur das Beispiel aus dem Buch. Ich habe Store (ID, Eintrittsdatum usw.), Tags, StoreTags, StoreLocation, StoreGeoCoordinates, StoreDescription
Dexter

Was ist, wenn Sie die Ergebnisse Ihrer zweiten Abfrage genommen und post.idvon dort die entsprechenden erhalten und die INKlausel in der letzten Abfrage verwenden? Oder ist es das, was du tust?
Patrick

Antworten:


2

Ich habe dies an einigen Stellen getan. Das Ausführen mehrerer einfacher Abfragen und das Erstellen einer ID-Liste in der Anwendungslogik, selbst wenn die ID-Liste mehr als 10.000 IDs enthält, führte zu erheblichen Leistungssteigerungen. Der Tisch, den ich abfragte, hatte ungefähr 5 Millionen Datensätze und ein JOIN war schmerzhaft langsam. Nach dem Wechsel zur Verwendung von IN mit einer ID-Liste dauerte es ungefähr 1% der Zeit, die der JOIN benötigte.


3

komplexe Abfragen in einfache aufteilen

Quatsch. Warum zusätzliche Anstrengungen unternehmen, wenn MySQL bereit ist, dies für Sie zu tun? Was die Leistung betrifft, gibt es wahrscheinlich keinen Unterschied, außer dass die aufgelösten Abfragen mehr Roundtrips zum Server erfordern.

OTOH, es gibt Fälle, in denen Sie den Optimierer überlisten können. Aber Ihr Beispiel war keines davon.

IN (Tausende von IDs) ist für den Server möglich, aber schmerzhaft. Es sortiert und de-dupt sie und belässt sie dann in einer Art Struktur für die wiederholte binäre Suche. Ich habe viele solcher Anfragen gesehen, aber nur die über 50.000 Artikel haben Augenbrauen hochgezogen.

Es gibt Zeiten, in denen dieses Umschreiben hilft:

SELECT ... ORDER BY ... LIMIT ...

->

SELECT b... 
FROM tbl b 
   JOIN ( SELECT id FROM TBL WHERE ... ORDER BY ... LIMIT ... ) a 
   ON a.id = b.id 

Damit soll jedoch vermieden werden, dass zusätzlicher Müll herumgeschleppt wird, der vom LIMIT weggeworfen wird.


0

Ich habe dies in einigen Fällen getan, in denen es zu einer signifikanten, messbaren Geschwindigkeitssteigerung kam. Andererseits hat dies in anderen Fällen nicht viel geholfen. Ich glaube nicht, dass es eine universelle Antwort im Sinne von "Ja, das ist immer gut" oder "Nein, das ist immer schlecht" gibt. Ich gehe davon aus, dass "der Abfrageoptimierer normalerweise eine bessere Lösung findet als ein Programmierer": Bisher habe ich nur wenige Eckfälle gefunden, in denen ich die Arbeit des Abfrageoptimierers wie diesen ausführen musste.

Wie bei jeder Optimierung: Überprüfen Sie Ihre spezifischen Daten, profilieren Sie das Programm (nicht nur die Abfrage!) Und prüfen Sie, ob der Unterschied real ist oder nur Wunschdenken.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.