2013-07-23 7 views
6

Auf einer einfachen, aber sehr großen Innodb-Tabelle, ich habe einen eindeutigen Index für Spalte A und ich möchte eine Liste von (ganzzahligen) Spalte B in der Reihenfolge der (ganzzahligen) Spalte AWarum erstellt MySQL Innodb "Sortierindex erstellen", wenn ein eindeutiger Index existiert?

Sehr einfache Abfrage, ich bin Durchblättern von Millionen von Datensätzen.

SELECT B FROM hugeTable ORDER BY A LIMIT 10000 OFFSET 500000

Dies dauert 10 Sekunden pro Abfrage auf einem sehr schnellen Server?

Filesort: Yes Filesort_on_disk: Yes Merge_passes: 9

Das macht keinen Sinn für mich, warum kann es verwenden, Index A nicht?

Erklärung zeigt einfach, keine möglichen Schlüssel und filesort.

Antwort

10

Wenn die Werte für Spalte B auf den Indexseiten nicht verfügbar sind, muss MySQL auf Seiten in der zugrunde liegenden Tabelle zugreifen. Auch gibt es kein Prädikat, das filtert, welche Zeilen betrachtet werden, und das bedeutet, dass MySQL sieht, dass ALLE Zeilen zurückgegeben werden müssen. Dies könnte erklären, warum der Index nicht verwendet wird.

Beachten Sie auch, dass die LIMIT-Operationen am Ende der Anweisung als fast der letzte Schritt im Ausführungsplan mit einigen Ausnahmen verarbeitet werden.

8.2.1.3. Optimizing LIMIT Queries http://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html

Ich vermute, dass Ihre Abfrage Verwendung eines abdeckenden Index, zum Beispiel „ON hugetable (A,B)“ machen könnte, den Sortiervorgang zu vermeiden.

Fehlen Sie einen abdeckenden Index, könnten Sie versuchen, die Abfrage so umzuschreiben, um zu sehen, ob dies den Index für Spalte A verwendet und eine Sortieroperation für Millionen von Zeilen vermeidet (um die ersten 510.000 zurückgegebenen Zeilen zu erhalten) in dieser Reihenfolge):

SELECT i.B 
    FROM (SELECT j.A 
      FROM hugeTable j 
      ORDER 
      BY j.A 
      LIMIT 10000 OFFSET 500000 
     ) k 
    JOIN hugetable i 
    ON i.A = k.A 
ORDER 
    BY k.A 

ich schlage vor, Sie nur auf die Inline-view-Abfrage ein EXPLAIN tun (wie k) aliased, und sehen, ob es zeigt "Using index."

Die äußere Abfrage wird wahrscheinlich immer noch eine "Using filesort" -Operation haben, aber das wird mindestens auf 10.000 Zeilen sein.

(Hinweis: Sie möchten eine "ORDER BY i.A" anstelle von "k.A" auf der äußeren Abfrage, um zu versuchen, und sehen, ob das einen Unterschied macht.)


NACHTRAG

Wenn Sie Ihre Frage nicht speziell ansprechen, sondern in Bezug auf die Leistung dieser Abfrage, wenn Sie eine Reihe von Zeilen "durchblättern", ist eine andere Option zu berücksichtigen, auf die "nächste" Seite zu gelangen, um den Wert von "A" zu verwenden die letzte Zeile, die bei der vorherigen Abfrage als "Startpunkt" für t abgerufen wurde Die nächste Reihe.

Die ursprüngliche Abfrage sieht aus, als ob sie "Seite 51" erhält (10.000 Zeilen pro Seite, Seite 51 wäre Zeilen 510.001 bis 520.000).

Wenn Sie auch den Wert von 'A' zurückgeben, und dies für die letzte Zeile beibehalten.Um die „nächste“ Seite zu bekommen, könnte die Abfrage tatsächlich sein:

SELECT i.B, k.A 
    FROM (SELECT j.A 
      FROM hugeTable j 
      WHERE j.A > $value_of_A_from_row_520000 
     -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
      LIMIT 10000 
     ) k 
    JOIN hugetable i 
    ON i.A = k.A 
    ORDER 
    BY k.A 

Wenn Sie auch den Wert für A von der „ersten“ Reihe gehalten, Sie, dass für die Sicherung einer Seite nutzen könnten. Das würde wirklich nur für vorwärts eine Seite oder zurück eine Seite funktionieren. Wenn Sie zu einer anderen Seite springen, müssen Sie die ursprüngliche Form der Abfrage verwenden und Zeilen zählen.

Verwandte Themen