Mysql-Geheimnisse für schnelle Abfragen – Verständnis des B+-Baumindex

1. Suche ohne Index

SELECT [列名列表] FROM 表名 WHERE 列名 = xxx;

1. Innerhalb einer Seite suchen

Unter der Annahme, dass derzeit wenige Datensätze in der Tabelle vorhanden sind, können alle Datensätze auf einer Seite gespeichert werden. Es kann entsprechend den unterschiedlichen Suchbedingungen in zwei Fälle unterteilt werden:

  • Suche nach Primärschlüssel
  • Suche nach anderen Spalten

2. Auf vielen Seiten finden

In den meisten Fällen sind die in unserer Tabelle gespeicherten Datensätze sehr groß, und es werden viele Datenseiten benötigt, um diese Datensätze zu speichern. Das Suchen von Datensätzen auf vielen Seiten kann in zwei Schritte unterteilt werden:

  1. Navigieren Sie zu der Seite, auf der sich der Datensatz befindet.
  2. Suchen Sie den entsprechenden Datensatz auf der Seite, auf der er sich befindet.

In Ermangelung eines Index, unabhängig davon, ob er auf dem Wert der Primärschlüsselspalte oder anderer Spalten basiert, können wir, da wir die Seite, auf der sich der Datensatz befindet, nicht schnell finden können, nur die doppelt verknüpfte Liste von der ersten Seite aus durchgehen. Auf jeder Seite, um den angegebenen Datensatz zu finden. Wenn in einer Tabelle viele Datensätze vorhanden sind, ist diese Sucheffizienz sehr gering.

Zweitens Index

Erstellen Sie zuerst eine Tabelle:

CREATE TABLE index_demo(
  c1 INT,
  c2 INT,
  c3 CHAR(1),
  PRIMARY KEY(c1)
 ) ROW_FORMAT = Compact;

Das Zeilenformat dieser Tabelle ist wie folgt:
Bildbeschreibung hier einfügen
record_type : Gibt den Datensatztyp an. 0 für normale Aufzeichnungen, 1 für Verzeichniseintragsaufzeichnungen, 2 für minimale Aufzeichnungen, 3 für maximale Aufzeichnungen

next_record : Gibt den Adress-Offset der nächsten Adresse relativ zu diesem Datensatz an. (Zum leichteren Verständnis werden in den folgenden Diagrammen Pfeile verwendet, um anzuzeigen, wer der nächste Datensatz ist.)

Um einige Datensätze auf die Seite zu setzen, ist:
Bildbeschreibung hier einfügen

1. Einfaches Indizierungsschema

Da die Datensätze auf jeder Seite unregelmäßig sind, wissen wir nicht, welche Datensätze unseren Suchkriterien entsprechen, also müssen wir alle Datenseiten der Reihe nach durchlaufen.

Wenn wir die Datenseiten der Datensätze, die wir finden müssen, schnell finden möchten, können wir ein weiteres Verzeichnis für die Datenseiten erstellen. Das etablierte Verzeichnis erfüllt vor allem:

  • Der Primärschlüsselwert des Benutzerdatensatzes auf der nächsten Datenseite muss größer sein als der Primärschlüsselwert des Benutzerdatensatzes auf der vorherigen Seite (vorausgesetzt: Jede unserer Datenseiten kann bis zu 3 Datensätze speichern).
INSERT INTO index_demo VALUES(1, 4, 'u'), (3, 9, 'd'), (5, 3, 'y');
Query OK, 3 rows affected (0.01 sec)

Bildbeschreibung hier einfügen
Jetzt fügen wir einen weiteren Datensatz ein:

INSERT INTO index_demo VALUES(4, 4, 'a');

Da Seite 10 nur bis zu 3 Datensätze aufnehmen kann, müssen wir eine neue Seite zuweisen:
Bildbeschreibung hier einfügen

Die Nummern neu zugewiesener Datenseiten dürfen nicht fortlaufend sein , was bedeutet, dass die von uns verwendeten Seiten im Speicherplatz möglicherweise nicht nebeneinander liegen. Sie stellen nur eine verknüpfte Listenbeziehung her, indem sie die Nummer der vorherigen Seite und der nächsten Seite beibehalten.

Der maximale Primärschlüsselwert des Benutzerdatensatzes auf Seite 10 ist 5, und der Primärschlüsselwert eines Datensatzes auf Seite 28 ist 4, da 5 > 4, sodass dies nicht dem Primärschlüsselwert des Benutzerdatensatzes im nächsten entspricht Datenseite muss größer sein als die Anforderung des Primärschlüsselwerts des Benutzerdatensatzes auf der vorherigen Seite. Wenn Sie also den Datensatz mit dem Primärschlüsselwert 4 einfügen, muss er von einer Datensatzverschiebung begleitet werden , d. h. dem Datensatz mit dem Primärwert 5 wird auf Seite 28 verschoben, und dann wird der Datensatz verschoben.Ein Datensatz mit einem Primärschlüsselwert von 4 wird auf Seite 10 eingefügt.

Dieser Vorgang wird Seitenaufteilung genannt:
Bildbeschreibung hier einfügen

  • Erstellen Sie einen Verzeichniseintrag für alle Seiten
    Da die Anzahl der Datenseiten möglicherweise nicht fortlaufend ist, kann der Effekt nach dem Einfügen vieler Datensätze in die Tabelle index_demo wie folgt sein: Bildbeschreibung hier einfügen
    Ich möchte schnell eine bestimmte Seite aus so vielen Seiten anhand der finden Primärschlüsselwert Für die Seiten, auf denen sich diese Datensätze befinden, müssen wir ein Verzeichnis für sie erstellen, und jede Seite entspricht einem Verzeichniseintrag. Bildbeschreibung hier einfügen
    Wir müssen nur ein paar Verzeichniseinträge einfügenKontinuierliche Speicherung im physischen Speicher, z. B. indem Sie sie in ein Array einfügen, können Sie anhand des Primärschlüsselwerts schnell einen Datensatz finden.

Ein einfaches Verzeichnis für die Datenseite ist fertig. Dieses Verzeichnis hat einen Alias ​​namens index .

2. Indexschema in InnoDB

Der Grund, warum das obige als einfaches Indizierungsschema bezeichnet wird, liegt darin, dass wir davon ausgehen, dass alle Verzeichniseinträge zusammenhängend im physischen Speicher gespeichert werden können, um die Dichotomie zu verwenden, um bestimmte Verzeichniselemente bei der Suche basierend auf dem Primärschlüsselwert schnell zu finden, dies jedoch getan hat einige Fragen:

  • InnoDB verwendet Seiten als Grundeinheit für die Verwaltung des Speicherplatzes, das heißt, es kann bis zu 16 KB kontinuierlichen Speicherplatz garantieren.Mit der Zunahme der Anzahl von Datensätzen in der Tabelle wird ein sehr großer kontinuierlicher Speicherplatz benötigt, um alle abzulegen Verzeichniseinträge. , was für Tabellen mit sehr vielen Datensätzen unpraktisch ist
    .
  • Wir fügen oft Einträge hinzu oder löschen sie. Angenommen, wir löschen alle Einträge auf Seite 28, und Seite 28 muss nicht existieren, was bedeutet, dass Verzeichniseintrag 2 nicht existieren muss, was den Verzeichniseintrag erfordert. Die Verzeichniseinträge nach 2 sind vorwärts bewegt.

Daher können wir die Datenseiten, die zuvor Benutzerdatensätze gespeichert haben, wiederverwenden, um Verzeichniseinträge zu speichern. Um sie von Benutzerdatensätzen zu unterscheiden, nennen wir diese Datensätze, die verwendet werden, um Verzeichniseinträge darzustellen, alsVerzeichniseintragsaufzeichnung

Wie unterscheidet InnoDB, ob ein Datensatz ein normaler Benutzerdatensatz oder ein Verzeichniseintragsdatensatz ist?

  • Durch das record_type-Attribut in den Datensatzkopfinformationen
    0: normaler Benutzerdatensatz 1: Verzeichniseintragsdatensatz 2: minimaler Datensatz 3: maximaler Datensatz
    Bildbeschreibung hier einfügen

Die Unterschiede zwischen Verzeichniseintragsdatensätzen und normalen Benutzerdatensätzen:

  1. Der record_type-Wert von Verzeichniseintragsdatensätzen ist 1 und der record_type-Wert von gewöhnlichen Benutzerdatensätzen ist 0.
  2. Der Katalogelementdatensatz hat nur zwei Spalten, den Primärschlüsselwert und die Seitennummer, während die Spalten des normalen Benutzerdatensatzes vom Benutzer definiert werden und viele Spalten sowie die von InnoDB selbst hinzugefügten versteckten Spalten enthalten können.
  3. Die Datensatzkopfinformationen haben ein Attribut min_rec_mask. Nur der Verzeichniseintragsdatensatz mit dem kleinsten Primärschlüsselwert auf der Seite, die den Verzeichniseintragsdatensatz speichert, hat den min_rec_mask-Wert von 1, und der min_rec_mask-Wert anderer Datensätze ist 0.

Daher können die Schritte zum Suchen von Datensätzen basierend auf einem Primärschlüsselwert grob in die folgenden zwei Schritte unterteilt werden:

  1. Gehen Sie zuerst zu der Seite, auf der der Verzeichniseintrag gespeichert ist , d. h. Seite 30, um den entsprechenden Verzeichniseintrag schnell durch Dichotomie zu finden. Da 12 < 20 < 209 , ist die Seite, auf der sich der entsprechende Datensatz befindet, Seite 9.
  2. Gehen Sie dann zu Seite 9, wo der Benutzerdatensatz gespeichert ist, und suchen Sie schnell den Benutzerdatensatz mit dem Primärschlüsselwert 20 gemäß der Dichotomie-Methode.

F: Es wird zwar gesagt, dass nur der Primärschlüsselwert und die entsprechende Seitennummer im Verzeichniseintragsdatensatz gespeichert werden, was viel kleiner ist als der vom Benutzerdatensatz benötigte Speicherplatz, aber eine Seite ist nur 16 KB groß und das Verzeichniseintragsdatensätze, die gespeichert werden können, sind ebenfalls begrenzt. Es enthält so viele Daten, dass eine Datenseite nicht ausreicht, um alle Verzeichniseintragsdatensätze zu speichern. Was soll ich tun?
A: Fügen Sie eine weitere Seite hinzu, um Verzeichniseintragsdatensätze zu speichern

Wir gehen davon aus, dass eine Seite, die Verzeichniseintragsdatensätze speichert, nur bis zu 4 Verzeichniseintragsdatensätze speichern kann, dann: Bildbeschreibung hier einfügen
Da nun mehr als eine Seite Verzeichniseintragsdatensätze speichert, wenn wir einen Benutzerdatensatz basierend auf dem Primärschlüsselwert finden wollen, it dauert ungefähr 3 Schritte:

  1. Identifizieren Sie die Datensatzseite des Katalogeintrags.
  2. Die Seite, auf der sich der Benutzerdatensatz tatsächlich befindet, wird durch die Datensatzseite des Verzeichniseintrags bestimmt.
  3. Suchen Sie einen bestimmten Datensatz auf der Seite, auf der der eigentliche Benutzerdatensatz gespeichert ist.

Frage: In Schritt 1 müssen wir die Seiten finden, auf denen Katalogartikeldatensätze gespeichert sind, aber diese Seiten befinden sich möglicherweise nicht nebeneinander im Speicherplatz.Wenn unsere Tabelle viele Daten enthält, gibt es viele Seiten Katalogeintragsdatensätze speichern Wie findet man schnell eine Seite, auf der Verzeichniseintragsdatensätze basierend auf dem Primärschlüsselwert gespeichert sind?
A: Dann wird für diese Seiten ein Verzeichnis höherer Ebene generiert, das Verzeichniseintragsdatensätze speichert.
Bildbeschreibung hier einfügen
Wir haben festgestellt, dass dieser Graph ein B+-Baum ist.

Unabhängig davon, ob es die Datenseiten sind, die Benutzerdatensätze speichern, oder die Datenseiten, die Verzeichniseintragsdatensätze speichern, speichern wir sie in der B+-Baumdatenstruktur, daher nennen wir diese Datenseiten auch Knoten .

Wie aus der Abbildung ersichtlich, unseretatsächlicher BenutzerdatensatzTatsächlich werden sie alle auf dem untersten Knoten des B+-Baums gespeichert. Diese Knoten werden auch Blattknoten genannt . Die restlichen Knoten, die zum Speichern von Verzeichniselementen verwendet werden, werden Nicht-Blatt-Knoten genannt. Der oberste Knoten des B+-Baums ist es auch Wurzelknoten genannt.

  • InnoDB legt fest, dass die unterste Schicht, d. h. die Schicht, die Benutzerdatensätze speichert, die 0. Schicht ist und dann der Reihe nach hinzugefügt wird.
  • Unter normalen Umständen wird der von uns verwendete B+-Baum 4 Schichten nicht überschreiten.
  • Um einen Datensatz über den Primärschlüsselwert zu finden, muss nur eine Suche innerhalb von höchstens 4 Seiten durchgeführt werden (3 Verzeichniselementseiten und eine Benutzerdatensatzseite finden), und da es auf jeder Seite ein Seitenverzeichnisseitenverzeichnis gibt), also in The Seite kann auch durch die Dichotomie-Methode schnell positioniert und aufgezeichnet werden.

1. Gruppierter Index

Der zuvor eingeführte B+-Baum ist selbst ein Verzeichnis oder selbst ein Index. Es hat zwei Funktionen:

  1. Verwenden Sie die Größe des Datensatz-Primärschlüsselwerts, um Datensätze und Seiten zu sortieren, was drei Bedeutungen beinhaltet:
  • Die Datensätze auf der Seite werden entsprechend der Größe des Primärschlüssels in einer einfach verknüpften Liste angeordnet .
  • Jede Seite, die Benutzerdatensätze speichert, ist außerdem in einer doppelt verknüpften Liste entsprechend der Größe des Primärschlüssels der Benutzerdatensätze auf der Seite angeordnet.
  • Seiten, die Verzeichniseintragsdatensätze speichern, sind in verschiedene Ebenen unterteilt, und Seiten in der gleichen Ebene sind auch in einer doppelt verknüpften Liste gemäß der Größe des Primärschlüssels der Verzeichniseintragsdatensätze in der Seite angeordnet.
  1. Die Blattknoten des B+-Baums speichern vollständige Benutzerdatensätze.
  • Ein vollständiger Benutzerdatensatz bedeutet, dass alle Spaltenwerte (einschließlich ausgeblendeter Spalten) in diesem Datensatz gespeichert werden.

Wir nennen einen B+-Baum mit diesen beiden Eigenschaften alsgeclusterter Indexwerden alle vollständigen Benutzerdatensätze in den Blattknoten dieses Clustered - Index gespeichert . Dieser Clustered-Index erfordert nicht, dass wir explizit die INDEX-Anweisung in der MySQL-Anweisung zum Erstellen verwenden, die InnoDB-Speicher-Engine erstellt den Clustered-Index automatisch für uns.

In der InnoDB-Speicher-Engine ist der Clustered-Index die Speichermethode für Daten (alle Benutzerdatensätze werden in den Blattknoten gespeichert), das heißt, der sogenannte Index sind die Daten und die Daten sind der Index.

2. Sekundärindex

Der gruppierte Index kann nur funktionieren, wenn die Suchbedingung der Primärschlüsselwert ist , da die Daten im B+-Baum
nach dem Primärschlüssel sortiert werden. Was ist, wenn wir andere Spalten als Suchkriterien verwenden möchten?

Wir können mehrere weitere B+-Bäume erstellen, und die Daten in verschiedenen B+-Bäumen verwenden unterschiedliche Sortierregeln. Beispielsweise verwenden wir die Größe der c2-Spalte als Sortierregel der Datenseite und der Datensätze auf der Seite und erstellen dann einen B+-Baum, wie in der Abbildung gezeigt:
Bildbeschreibung hier einfügen
Dieser B+-Baum unterscheidet sich vom oben eingeführten Clustered-Index :

  • Verwenden Sie die Größe der c2-Spalte des Datensatzes, um Datensätze und Seiten zu sortieren, was drei Bedeutungen beinhaltet:
  1. Die Datensätze auf der Seite werden in einer einfach verknüpften Liste entsprechend der Größe der c2-Spalte angeordnet.
  2. Jede Seite , die Benutzerdatensätze speichert, ist außerdem in einer doppelt verknüpften Liste gemäß der Größe der in der Seite aufgezeichneten c2-Spalte angeordnet.
  3. Die Seiten, die die Verzeichniseintragsdatensätze speichern, sind in verschiedene Ebenen unterteilt, und die Seiten in der gleichen Ebene sind auch in einer doppelt verknüpften Liste gemäß der Größe der c2-Spalte der Verzeichniseintragsdatensätze in der Seite angeordnet.
  • Der Blattknoten des B+-Baums speichert nicht kompletten Benutzerdatensatz , sondern nur die Werte der beiden Spalten c2 Spalte + Primärschlüssel.
  • Der Katalogeintragssatz ist nicht mehr die Kombination aus Primärschlüssel + Seitennummer, sondern die Kombination aus Spalte c2 + Seitennummer.

Da die Blattknoten beim Nachschlagen von Benutzerdatensätzen nur c2- und Primärschlüsselspalten speichern, müssen wir im Clustered-Index gemäß dem Primärschlüsselwert erneut nach den vollständigen Benutzerdatensätzen suchen.Dieser Vorgang wird Rückgabetabelle genannt

F: Warum nicht den vollständigen Benutzerdatensatz direkt in den Blattknoten einfügen?
A: Obwohl es nicht erforderlich ist, die Tabelle zurückzugeben, um vollständige Benutzerdatensätze in Blattknoten zu speichern, entspricht dies dem Kopieren aller Benutzerdatensätze jedes Mal, wenn ein B+-Baum erstellt wird, was eine Verschwendung von Speicherplatz darstellt. Daher erfordert dieser auf Nicht-Primärschlüsselspalten basierende B+-Baum eine Tabellenrückgabeoperation, um den vollständigen Benutzerdatensatz zu lokalisieren, sodass dieser B+-Baum ebenfalls aufgerufen wirdSekundärindexoder Sekundärindex.

Da wir die Größe der c2-Spalte als Sortierung des B+-Baums verwenden, nennen wir diesen B+-Baum auch einen Index für die c2-Spalte .

3. Gemeinsamer Index

Wir können auch die Größe mehrerer Spalten gleichzeitig als Sortierregel verwenden , d. h. um Indizes für mehrere Spalten gleichzeitig zu erstellen . Beispielsweise möchten wir den B+-Baum nach der Größe von c2 und sortieren c3-Spalten, die zwei Bedeutungen enthalten:

  • Sortieren Sie zunächst jeden Datensatz und jede Seite nach Spalte c2.
  • Falls die c2-Spalte des Datensatzes gleich ist, wird die c3-Spalte zum Sortieren verwendet
    Bildbeschreibung hier einfügen
  • Jeder Datensatz wird zuerst nach dem Wert der c2-Spalte sortiert, wenn die c2-Spalte des Datensatzes gleich ist, wird er nach dem Wert der c3-Spalte sortiert.
  • Der Benutzerdatensatz am Blattknoten des B+-Baums besteht aus den Spalten c2, c3 und dem Primärschlüssel c1.

Der B+-Baum, der mit der Größe der c2- und c3-Spalten erstellt wurde, wie die Sortierung genannt wirdgemeinsamer Index, der im Wesentlichen ein sekundärer Index ist. Seine Bedeutung unterscheidet sich von der Aussage, die Spalten c2 und c3 separat zu indizieren.

  • Das Erstellen eines gemeinsamen Indexes erstellt nur einen B+-Baum, wie oben gezeigt.
  • Durch Indizieren der Spalten c2 bzw. c3 werden 2 B+-Bäume mit der Größe der Spalten c2 bzw. c3 als Sortierregeln erstellt.

3. Angelegenheiten, die Aufmerksamkeit erfordern

Als der B+-Baumindex früher eingeführt wurde, wurden zum besseren Verständnis zuerst die Blattknoten gezeichnet, die Benutzerdatensätze speichern, und dann die inneren Knoten, die Verzeichniseintragsdatensätze speichern, aber tatsächlich der Bildungsprozess des B+-Baums ist wie folgt:

  1. Immer wenn ein B+-Baumindex für eine Tabelle erstellt wird (ein gruppierter Index wird nicht künstlich erstellt, er ist standardmäßig vorhanden), wird eine Stammknotenseite für diesen Index erstellt . Wenn zunächst keine Daten in der Tabelle vorhanden sind, gibt es weder einen Benutzerdatensatz noch einen Verzeichniseintragsdatensatz in dem Wurzelknoten, der jedem B+-Baumindex entspricht.
  2. Speichern Sie beim Einfügen von Benutzerdatensätzen in die Tabelle zuerst die Benutzerdatensätze in diesem Stammknoten.
  3. Wenn der freie Speicherplatz im Stammknoten erschöpft ist, fahren Sie mit dem Einfügen von Datensätzen fort. Zu diesem Zeitpunkt werden alle Datensätze im Stammknoten auf eine neu zugewiesene Seite kopiert, beispielsweise Seite a, und dann wird die Seitenaufteilungsoperation ausgeführt diese neue Seite, um eine weitere neue Seite zu erhalten, wie z. B. Seite b. Zu diesem Zeitpunkt wird der neu eingefügte Datensatz entsprechend der Größe des Schlüsselwerts (d. h. dem Primärschlüsselwert im Clustered-Index, dem Wert der entsprechenden Indexspalte im Sekundärindex) Seite a oder Seite zugeordnet. und der Stammknoten wird aktualisiert Eine Seite zum Speichern von Katalogeintragsdatensätzen .

Der Wurzelknoten eines B+-Baumindex wird sich seit seiner Geburt nicht bewegen . Auf diese Weise wird, solange wir einen Index für eine Tabelle erstellen, die Seitennummer ihres Stammknotens irgendwo aufgezeichnet, und wann immer die InnoDB-Speicher-Engine diesen Index verwenden muss, wird sie den Stammknoten aus diesem festen herausnehmen Ort Die Seitennummer für den Zugriff auf diesen Index.

Der Inhalt, der im Verzeichniseintrag im inneren Knoten des B+-Baumindex aufgezeichnet wird, ist die Kombination aus Indexspalte + Seitenzahl , aber diese Kombination ist für Sekundärindizes etwas ungenau. Wir müssen sicherstellen, dass die Verzeichniseintragsdatensätze von Knoten auf derselben Ebene des B+-Baums mit Ausnahme des Seitenzahlfelds eindeutig sind .

Daher besteht der vom Verzeichniseintrag des inneren Knotens des sekundären Index aufgezeichnete Inhalt tatsächlich aus drei Teilen:

  • der Wert der Indexspalte
  • Primärschlüsselwert
  • Seitennummer

In InnoDB ist der Index data, das heißt, der Blattknoten des B+-Baums des Clustered Index enthält bereits alle vollständigen Benutzerdatensätze.Das MyISAM-Indexschema verwendet zwar ebenfalls eine Baumstruktur, kombiniert jedoch Index und Daten getrennt.

Viertens: Erstellen und löschen Sie Indizes in MySQL

InnoDB und MyISAM erstellen automatisch einen B+-Baumindex für den als UNIQUE deklarierten Primärschlüssel oder die als UNIQUE deklarierte Spalte, aber wenn wir einen Index für andere Spalten erstellen möchten, müssen wir ihn explizit angeben.

#创建
CREATE TALBE 表名 (
  各种列的信息 ··· ,
  [KEY|INDEX] 索引名 (需要被索引的单个列或多个列)
)

ALTER TABLE 表名 ADD [INDEX|KEY] 索引名 (需要被索引的单个列或多个列);

ALTER TABLE 表名 DROP [INDEX|KEY] 索引名;

#删除
ALTER TABLE 表名 DROP INDEX 索引名;

Wenn wir beispielsweise beim Erstellen der Tabelle index_demo einen gemeinsamen Index zu den Spalten c2 und c3 hinzufügen möchten, können wir die Anweisung zur Tabellenerstellung wie folgt schreiben:

CREATE TABLE index_demo(
	c1 INT,
	c2 INT,
	c3 CHAR(1),
	PRIMARY KEY(c1),
	INDEX idx_c2_c3 (c2, c3)
);

Supongo que te gusta

Origin blog.csdn.net/myjess/article/details/115550686
Recomendado
Clasificación