Ich habe zwei Tische - comments
und votes
:
comments(id, text, user_id, page_id)
votes(id, value)
Die votes
Tabelle enthält 2.000.000 Zeilen .
Ich habe die folgende Abfrage erstellt:
SELECT SUM(votes.value),
comments.text,
comments.comment_id
FROM comments, votes
WHERE comments.comment_id = votes.comment_id AND comments.page_id = $page_id
GROUP BY comment_id;
Die Abfrage läuft ungefähr 12 Sekunden. Ist das normal?
SHOW PROCESSLIST
sagt, dass es in eine temporäre Tabelle kopiert. Dies scheint langsam zu sein. Ist es notwendig, eine temporäre Tabelle zu verwenden?
Antworten:
In der Welt der RDBMS sind temporäre Tabellen eine Tatsache des Lebens. Es zeigt nur in JOINs seinen hässlichen Kopf .
Selbst der schlimmste Fall eines JOIN ist der entartete JOIN, eine Abfrage einer Tabelle.
Da temporäre Tabellen immer in unsere Abfragen (in unser Leben) eingehen, ist das Beste, was Sie tun können, temporäre Tabellen zu verhungern. Machen Sie sie so kompakt wie möglich. Was meine ich ???
Hier ist Ihre Anfrage:
Bei Ihrer Abfrage wird tatsächlich eine Tabelle erstellt, die sich aus einer Verknüpfung von Kommentaren und Stimmen ergibt, deren Zeilenanzahl die Anzahl der Kommentare mal 2.000.000 ist. Da temporäre Tabellen keine Indizes haben, treten immer kartesische Verknüpfungen mit den temporären Tabellen auf. Die WHERE-Klausel wird auf dem Weg angewendet, dann die GROUP BY-Summation. Vergessen Sie nicht, dass die temporäre Tabelle auch die Textspalte enthält. Das sind viele Textdaten, die in der JOIN-Phase verschoben werden müssen.
Lassen Sie uns Ihre Anfrage umgestalten
Sie können sozusagen die WHERE-Klausel am Pass beachten. Hier ist, wie:
Diese Abfrage enthält nur die erforderlichen Schlüssel aus der Kommentartabelle.
Sammeln Sie als Nächstes comment_ids aus den Stimmen
Dies ist eigentlich das Schlimmste. Mit 2 Millionen Zeilen und 4 Bytes pro comment_id und 4 Bytes für die Summe ist dies im schlimmsten Fall eine 16-MB-Tabelle.
Kombinieren Sie als Nächstes die Schlüssel der Kommentare mit den übereinstimmenden Schlüsseln in den Stimmen.
Nachdem die Schlüssel aus den Kommentaren und die Summe der Werte aus den Stimmen abgerufen wurden, besteht der letzte Teil darin, die Kommentar-IDs wieder mit der ursprünglichen Kommentartabelle zu verbinden und die Textfelder abzurufen.
Bevor diese überarbeitete Abfrage so schnell wie möglich ausgeführt werden kann, müssen Sie ordnungsgemäß indizieren.
Hier sind die Indizes, die Sie benötigen:
Sie möchten den ersten Index, da er Zeilen nach page_id gruppiert. Sie möchten den zweiten Index, da er Zeilen nach comment_id gruppiert. Tatsächlich werden diese beiden Indizes Deckungsindizes genannt . Warum ist das wichtig ??? Dies ist wichtig, da die Unterabfragen nur die erforderlichen Daten aus dem Index abrufen und niemals die Haupttabelle berühren. Auf die Kommentartabelle wird nur einmal zugegriffen, wenn alle benötigten Schlüssel in den Unterabfragen zusammen kompiliert wurden.
Versuche es !!!
Wenn eine Syntax nicht funktioniert, kommentieren Sie bitte die Frage und lassen Sie es mich wissen !!!
quelle
Angenommen, dies ist MySQL, können Sie mithilfe der
EXPLAIN
Syntax herausfinden, wie die Abfrage ausgeführt wird:Die erste Vermutung ist, dass Sie Indizes für die Spalten benötigen, denen Sie in der Abstimmtabelle beitreten.
quelle