2010-12-16 9 views
2
SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY SourceId, ExternalProductId 
HAVING cnt > 1 

Es gibt einen Index für (ExternalProductId, SourceId, AnotherField). Ein Explain zeigt an, dass der Index verwendet wird. Dies wird in der „Extra“ Spalte gedruckt von erklären:Warum kopiert die folgende Abfrage Tabellendaten?

Using where; Using index; Using temporary; Using filesort 

Wenn ich die Abfrage, die ich über SHOW PROCESS sehen laufen:

Copying to tmp table on disk 

Kann ich diese Abfrage zwicken an seinem Platz auf dem Index zu arbeiten? Es macht mir auch nichts aus, wenn die Ergebnisse etwas ungenau sind, weil andere Prozesse gleichzeitig an dieser Tabelle arbeiten. Kann ich die Isolationsstufe ändern, um die Leistung der Abfrage zu erhöhen?

+2

Ich denke, Sie haben einige Missverständnisse. Eine temporäre Tabelle bedeutet nicht, dass sie alle Daten aus der Tabelle kopiert, um ihre Arbeit zu erledigen. Es bedeutet nur das Kopieren eines Zwischenergebnisses in eine temporäre Tabelle zur weiteren Verarbeitung. Die temporäre Tabelle enthält wahrscheinlich alle Datensätze, bei denen die ExternalProductID nicht null ist, und die Spalte cnt, um die Klausel 'HAVING' auszuwerten. Zweitens hat die Transaktionsisolation nichts mit temporären Tabellen zu tun. – bot403

+0

@ bot403 - Ich habe gerade mit unserem DBA gesprochen und er stimmt dir zu. Ich glaube, Ihr Kommentar ist die bisher beste Antwort auf diese Frage. – ripper234

+0

Ja, ich denke, die Antwort ist sowohl mein # 1 als auch Ajreals Indexvorschlag. – bot403

Antwort

3

Wenn Sie die Spalten in Ihrem GROUP BY umkehren, um mit der Reihenfolge der ersten beiden Felder Ihres zusammengesetzten Index übereinzustimmen, verwendet es Ihren zusammengesetzten Index viel effektiver.

SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY ExternalProductId, SourceId 
HAVING cnt > 1 

Ihre Abfrageausführungs Ebene sollte in 'Using where; Using index' drehen, und loszuwerden sowohl die temporären Tabelle und filesort durch die anderen GROUP BY verursacht.

Sie erhalten immer noch die gleichen Ergebnisse, aber es wird in einer etwas anderen Reihenfolge sein.

+0

Sieht gut aus, das Explain zeigt jetzt keine temporäre Tabelle. Ich werde die Laufzeit der Abfrage messen, um festzustellen, ob es einen Unterschied gibt. – ripper234

0

Ein paar Dinge zu versuchen:

  1. MySQL automatisch sortiert mit einer Gruppe von. Wenn Sie sich nicht um die Sortierreihenfolge kümmern, fügen Sie eine Klausel 'ORDER BY NULL' hinzu. Das wird den Filesort und möglicherweise die temporäre Tabelle entfernen.

  2. Entfernen Sie die Anzahl (*) und verwenden Sie den Namen einer Spalte im Index anstelle des Platzhalters.

Auch. Was ist dein Index? Können Sie uns die vollständige Tabelle create statement zeigen?

+0

ORDER BY NULL verwendet immer noch eine temporäre Tabelle - siehe die akzeptierte Antwort. – ripper234

Verwandte Themen