MySQL indiziert die Wartung


12

Ich habe viel darüber recherchiert, wie Indizes in MySQL verwaltet werden können, um eine Fragmentierung zu verhindern und die Ausführung einiger Abfragen irgendwie zu optimieren.

Ich kenne diese Formel, die das Verhältnis zwischen dem für eine Tabelle maximal verfügbaren Speicherplatz und dem von Daten und Indizes verwendeten Speicherplatz berechnet.

Meine Hauptfragen sind jedoch noch unbeantwortet. Vielleicht liegt dies an der Tatsache, dass ich mit der Indexpflege in SQL Server vertraut bin und ich denke, dass sie in MySQL irgendwie ähnlich sein sollte.

In SQL Server können mehrere Indizes vorhanden sein, von denen jeder unterschiedliche Fragmentierungsstufen aufweisen kann. Dann können Sie eine auswählen und eine 'REORGANIZE'- oder' REBUILD'-Operation in diesem bestimmten Index ausführen, ohne den Rest zu beeinflussen.

Nach meinem besten Wissen gibt es keine "Tabellenfragmentierung" als solche, und SQL Server bietet kein Tool zum Beheben der "Tabellenfragmentierung". Es werden Tools zum Überprüfen der Indexfragmentierung (verstanden als Verhältnis zwischen der Anzahl der von einem Index verwendeten Seiten und der Fülle dieser Seite und der Kontiguität) sowie der internen und externen Fragmentierung bereitgestellt.

All das ist ziemlich einfach zu verstehen, zumindest für mich.

Wenn es darum geht, Indizes in MySQL zu verwalten, gibt es nur das oben erwähnte Konzept der Tabellenfragmentierung.

Eine Tabelle in MySQL kann mehrere Indizes haben, aber wenn ich das Fragmentierungsverhältnis mit dieser berühmten Formel überprüfe, sehe ich nicht die Fragmentierung jedes Index, sondern die Tabelle als Ganzes.

Wenn ich die Indizes in MySQL optimieren möchte, wähle ich keinen bestimmten Index für die Bearbeitung aus (wie in SQL Server). Stattdessen führe ich eine 'OPTIMIZE'-Operation in der gesamten Tabelle aus, die vermutlich alle Indizes betrifft.

Wenn die Tabelle in MySQL optimiert wird, wird das Verhältnis zwischen dem von Daten + Indizes verwendeten Speicherplatz und dem Gesamtspeicherplatz reduziert, was auf eine physische Neuorganisation der Festplatte hindeutet, was sich in einer Reduzierung des physischen Speicherplatzes niederschlägt. Bei der Indexfragmentierung geht es jedoch nicht nur um den physischen Speicherplatz, sondern auch um die Struktur des Baums, die im Laufe der Zeit aufgrund von Einfügungen und Aktualisierungen geändert wurde.

Endlich habe ich eine Tabelle in InnoDB / MySQL bekommen. Diese Tabelle enthält 3 Millionen Datensätze, 105 Spalten und 55 Indizes. Es sind 1,5 GB ohne Indizes, die 2,1 GB betragen.

Diese Tabelle wird tausende Male am Tag zum Aktualisieren und Einfügen aufgerufen (wir löschen keine Datensätze).

Diese Tabelle wurde jahrelang erstellt und ich weiß mit Sicherheit, dass niemand Indizes verwaltet.

Ich hatte erwartet, dort eine große Fragmentierung zu finden, aber wenn ich die Fragmentierungsberechnung wie vorgeschrieben durchführe

free_space / (data_length + index_length)

Es stellt sich heraus, dass ich nur eine Fragmentierung von 0,2% habe. IMHO ist das ziemlich unrealistisch.

Die großen Fragen sind also:

  1. Wie überprüfe ich die Fragmentierung eines bestimmten Index in MySQL, nicht der gesamten Tabelle?
  2. Behebt OPTIMIZE TABLE tatsächlich die interne / externe Fragmentierung eines Index wie in SQL Server?
  3. Wenn ich eine Tabelle in MySQL optimiere, werden dann tatsächlich alle Indizes in der Tabelle neu erstellt?
  4. Ist es realistisch zu glauben, dass die Reduzierung des physischen Speicherplatzes eines Index (ohne den Baum selbst neu zu erstellen) tatsächlich zu einer besseren Leistung führt?

Optimize Table bereinigt sicherlich den Clustered Index auf innodb

1
Es ist eine großartige Frage, nur keine Programmierfrage. Wird dorthin bewegt, wo es hingehört:>

Antworten:


6

Die Indexfragmentierung wird stark überbewertet. Mache dir darüber keine Sorgen.

Zwei benachbarte, etwas leere Blöcke werden von InnoDB als natürliche Verarbeitung zusammengeführt.

Durch zufällige Aktionen auf einem BTree wird es auf natürliche Weise zu durchschnittlich 69% voll. Sicher, das ist nicht 100%, aber der Aufwand für das "Reparieren" lohnt sich nicht.

SHOW TABLE STATUS gibt Ihnen einige Metriken, aber sie sind fehlerhaft - "Data_free" enthält bestimmten "freien" Speicherplatz, aber keinen anderen "freien" Speicherplatz.

In jedem Block ist nicht genutzter Speicherplatz vorhanden. freie 16KB Blöcke; freie "Extents" (nMB-Chunks); MVCC-Zeilen, die darauf warten, geerntet zu werden; Nicht-Blattknoten haben ihre eigene Fragmentierung; usw.

Percona und Oracle haben unterschiedliche Sichtweisen auf die Größe (Anzahl der Blöcke) eines Index. Ich finde keinen von ihnen wegen der begrenzten Definition von "frei" nützlich. Es scheint, dass Blöcke (jeweils 16 KB) in Blöcken (mehrere MB) zugewiesen werden, was zu der Annahme führt, dass alle Arten von Fragmentierung vorliegen. In der Realität ist es normalerweise nur der größte Teil eines dieser Multi-MB-Blöcke. Und OPTIMIZE TABLEmacht nicht unbedingt den Raum wieder gut.

Wenn SQL Server BTrees verwendet, liegt es an der Aussage, dass "keine Fragmentierung" vorliegt. Überlegen Sie, was bei einem "Block Split" passiert. Oder denken Sie an den Aufwand einer kontinuierlichen Defragmentierung. So oder so verlierst du.

Beachten Sie außerdem, dass eine Tabelle und ein Index im Wesentlichen identische Strukturen sind:

  • B + Tree, basierend auf einem Index
  • Die "Daten" basieren auf dem PRIMARY KEY; Jeder Sekundärindex ist ein B + -Baum, der auf seinem Index basiert.
  • Der Blattknoten der "Daten" enthält alle Spalten der Tabelle.
  • Der Blattknoten eines Sekundärindex enthält die Spalten dieses Sekundärindex sowie die Spalten des PRIMARY KEY.

Wenn innodb_file_per_table = ONdies der Fall ist, können Sie die Schrumpfung (falls vorhanden) nach OPTIMIZE TABLE anhand der .ibdDateigröße deutlich erkennen . Denn OFFdie Informationen sind vergraben ibdata1, SHOW TABLE STATUSkönnen aber ziemlich genau sein, da jeder "freie" Speicherplatz zu jeder Tabelle gehört. Nun, bis auf die vorab zugewiesenen Brocken.

Möglicherweise stellen Sie fest, dass eine frisch optimierte Datei pro Tabelle genau 4M, 5M, 6M oder 7M Data_free enthält. Dies ist wiederum die Vorabzuweisung und das Versäumnis, Ihnen die winzigen Details zu geben.

Ich arbeite seit über einem Jahrzehnt mit InnoDB zusammen. Ich habe mit Tausenden von großen und kleinen Tischen gearbeitet. Ich sage, dass nur ein Tisch von tausend wirklich braucht OPTIMIZE TABLE. Die Verwendung auf anderen Tischen ist eine Verschwendung.

105 Spalten sind viel, aber vielleicht nicht zu viele.

Haben Sie 55 Indizes für eine Tabelle? Das ist schlecht. Das sind 55 Updates pro INSERT. Lassen Sie uns das weiter diskutieren. Denken Sie daran, dass dies INDEX(a)nutzlos ist, wenn Sie auch haben INDEX(a,b). Und INDEX(flag)ist wegen geringer Kardinalität nutzlos. ( INDEX(flag, foo)Kann aber nützlich sein.)

Q1: Es gibt keine gute Möglichkeit, die Daten oder die Sekundärindizes auf alle Formen der Fragmentierung zu überprüfen.

Q2, Q3: OPTIMIZE TABLEErstellt die Tabelle durch CREATEingeine neue Tabelle und INSERTingalle Zeilen neu, dann RENAMEingund DROPping. Durch das erneute Einfügen der Daten in PK-Reihenfolge wird sichergestellt, dass die Daten gut defragmentiert sind. Die Indizes sind eine andere Sache.

F4: Sie könnten DROP und reCREATEjeden Index bereinigen. Dies ist jedoch ein äußerst langsamer Prozess. 5.6 hat einige Beschleunigungen, aber ich weiß nicht, ob sie bei der Defragmentierung helfen.

Es ist auch möglich ALTER TABLE ... DISABLE KEYS, dann ENABLEsie. Dies kann zu einer effizienteren Neuerstellung aller Sekundärindizes auf einmal führen.


Rick, ich meinte '105' Felder, keine Dateien
Nicolas

1

Wie überprüfe ich die Fragmentierung eines bestimmten Index in MySQL, nicht der gesamten Tabelle?

Bestehen.

Behebt OPTIMIZE TABLE tatsächlich die interne / externe Fragmentierung eines Index wie in SQL Server?

Die Tabelle und ihre Indizes werden vollständig neu erstellt.

Wenn ich eine Tabelle in MySQL optimiere, werden dann tatsächlich alle Indizes in der Tabelle neu erstellt?

Das ist die gleiche Frage mit der gleichen Antwort.

Ist es realistisch zu glauben, dass die Reduzierung des physischen Speicherplatzes eines Index (ohne den Baum selbst neu zu erstellen) tatsächlich zu einer besseren Leistung führt?

Es ist nicht realistisch zu glauben, dass Sie den Platz reduzieren könnten, ohne den Baum neu zu erstellen. Sie gehen zusammen.


Um # 1 zu beantworten: Es ist zwar nicht sehr genau, SHOW TABLE STATUS LIKE 'mytable'würde aber einen Hinweis in der data freeSpalte geben. dev.mysql.com/doc/refman/5.6/en/show-table-status.html
Jehad Keriaki

Ich weiß, aber das fehlt immer noch der Platz eines bestimmten Index
Nicolas
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.