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:
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;
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:
SELECT comment_id FROM comments WHERE page_id = $page_id;
Diese Abfrage enthält nur die erforderlichen Schlüssel aus der Kommentartabelle.
Sammeln Sie als Nächstes comment_ids aus den Stimmen
SELECT comment_id,SUM(value) sumofvalues FROM votes;
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.
SELECT BB.* FROM
(SELECT comment_id FROM comments WHERE page_id = $page_id) AA
INNER JOIN
(SELECT comment_id,SUM(value) sumofvalues FROM votes GROUP BY comment_id) BB
USING (comment_id);
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.
SELECT
B.sumofvalues,A.text,A.comment_id
FROM
comments A INNER JOIN
(
SELECT BB.*
FROM
(SELECT comment_id FROM comments WHERE page_id = $page_id) AA
INNER JOIN
(SELECT comment_id,SUM(value) sumofvalues
FROM votes GROUP BY comment_id) BB
USING (comment_id)
) B
USING (comment_id);
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:
ALTER TABLE comments ADD INDEX pageid_commentid_ndx (page_id,comment_id);
ALTER TABLE votes ADD INDEX commentid_value_ndx (comment_id,value);
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 !!!