Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie funktionieren MySQL-Indizes?

Das erste, was Sie wissen müssen, ist, dass Indizes eine Möglichkeit sind, das Scannen der gesamten Tabelle zu vermeiden, um das gesuchte Ergebnis zu erhalten.

Es gibt verschiedene Arten von Indizes und sie sind in der Speicherschicht implementiert, es gibt also keinen Standard zwischen ihnen und sie hängen auch von der verwendeten Speicher-Engine ab.

InnoDB und der B+Tree-Index

Für InnoDB ist der häufigste Indextyp der B+Tree-basierte Index, der die Elemente in einer sortierten Reihenfolge speichert. Außerdem müssen Sie nicht auf die echte Tabelle zugreifen, um die indizierten Werte zu erhalten, wodurch Ihre Abfrage viel schneller zurückkehrt.

Das "Problem" bei diesem Indextyp besteht darin, dass Sie den Wert ganz links abfragen müssen, um den Index zu verwenden. Wenn Ihr Index also zwei Spalten hat, z. B. Nachname und Vorname, ist die Reihenfolge, in der Sie diese Felder abfragen, sehr wichtig .

Also, gegeben die folgende Tabelle:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

Diese Abfrage würde den Index nutzen:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

Aber die folgende nicht

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

Weil Sie den first_name abfragen Spalte zuerst und es ist nicht die Spalte ganz links im Index.

Dieses letzte Beispiel ist noch schlimmer:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

Denn jetzt vergleichen Sie den ganz rechten Teil des ganz rechten Felds im Index.

Der Hash-Index

Dies ist ein anderer Indextyp, der leider nur vom Speicher-Backend unterstützt wird. Es ist blitzschnell, aber nur für vollständige Suchen nützlich, was bedeutet, dass Sie es nicht für Operationen wie > verwenden können , < oder LIKE .

Da es nur für das Speicher-Backend funktioniert, werden Sie es wahrscheinlich nicht sehr oft verwenden. Der Hauptfall, den ich mir jetzt vorstellen kann, ist der, dass Sie eine temporäre Tabelle im Speicher mit einer Reihe von Ergebnissen aus einer anderen Auswahl erstellen und viele andere Auswahlen in dieser temporären Tabelle unter Verwendung von Hash-Indizes durchführen.

Wenn Sie einen großen VARCHAR haben -Feld können Sie die Verwendung eines Hash-Index bei Verwendung eines B-Baums "emulieren", indem Sie eine weitere Spalte erstellen und einen Hash des großen Werts darauf speichern. Angenommen, Sie speichern eine URL in einem Feld und die Werte sind ziemlich groß. Sie könnten auch ein ganzzahliges Feld namens url_hash erstellen und verwenden Sie eine Hash-Funktion wie CRC32 oder eine andere Hash-Funktion, um die URL beim Einfügen zu hashen. Und wenn Sie diesen Wert abfragen müssen, können Sie so etwas tun:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

Das Problem mit dem obigen Beispiel ist, dass seit dem CRC32 -Funktion einen ziemlich kleinen Hash generiert, werden Sie am Ende viele Kollisionen in den Hash-Werten haben. Wenn Sie genaue Werte benötigen, können Sie dieses Problem wie folgt beheben:

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

Es lohnt sich immer noch, Dinge zu hashen, auch wenn die Kollisionszahl hoch ist, da Sie nur den zweiten Vergleich (den String-Eins) mit den wiederholten Hashes durchführen.

Leider müssen Sie bei dieser Technik immer noch auf die Tabelle tippen, um die url zu vergleichen Feld.

Abschluss

Einige Fakten, die Sie jedes Mal berücksichtigen sollten, wenn Sie über Optimierung sprechen möchten:

  1. Der Vergleich von ganzen Zahlen ist viel schneller als der Vergleich von Zeichenfolgen. Es lässt sich am Beispiel der Emulation des Hash-Index in InnoDB veranschaulichen .

  2. Vielleicht macht das Hinzufügen zusätzlicher Schritte in einem Prozess ihn schneller, nicht langsamer. Dies kann anhand der Tatsache veranschaulicht werden, dass Sie ein SELECT optimieren können indem Sie es in zwei Schritte aufteilen, indem Sie den ersten dazu bringen, Werte in einer neu erstellten In-Memory-Tabelle zu speichern und dann die schwereren Abfragen für diese zweite Tabelle auszuführen.

MySQL hat auch andere Indizes, aber ich denke, der B+Tree-Index ist der meistgenutzte aller Zeiten und der Hash-Index ist gut zu wissen, aber Sie können die anderen in MySQL-Dokumentation .

Ich empfehle Ihnen dringend, das Buch "High Performance MySQL" zu lesen, die obige Antwort basierte definitiv auf dem Kapitel über Indizes.