Ich habe eine Anwendung, die nur auf Gleichheit auswählt, und ich denke, ich sollte einen Hash-Index über einen Btree-Index verwenden. Zu meiner großen Enttäuschung werden Hash-Indizes in MyISAM oder InnoDB nicht unterstützt. Was ist damit?
35
Antworten:
Viele Datenbanken unterstützen keine Hash-basierten Indizes überhaupt nicht .
Damit eine Hash-Tabelle effizient ist, müssen Sie die Anzahl der Zeilen kennen, die wahrscheinlich vorhanden sind. Andernfalls ist die Basis-Hash-Tabelle viel zu groß (viele leere Einträge, Platzverschwendung und möglicherweise Festplatten-E / A) oder zu klein Eine Indirektion wird häufig verwendet (möglicherweise mehrere Indirektionsebenen oder, noch schlimmer, wenn die Hash-Implementierung einstufig ist, kann dies dazu führen, dass eine lineare Suche über eine angemessene Anzahl von Datensätzen durchgeführt wird), und an diesem Punkt sind die Dinge wahrscheinlich nicht effizienter als baumbasiert Index sowieso.
Um im Allgemeinen nützlich zu sein (dh in der Regel besser als die Alternative), muss der Index gelegentlich neu erstellt werden, wenn Daten wachsen (und schrumpfen), was zu einem erheblichen zeitweiligen Overhead führen kann. Dies ist bei speicherbasierten Tabellen normalerweise in Ordnung, da die Neuerstellung wahrscheinlich ziemlich schnell sein wird (da sich die Daten immer im RAM befinden und in keinem Fall massiv sein werden), aber die Neuerstellung eines großen Index auf der Festplatte ist ein Problem Sehr schwere Operation (und IIRC mySQL unterstützt keine Live-Index-Neuerstellungen, so dass während der Operation eine Tabellensperre besteht).
Daher werden Hash-Indizes in Speichertabellen verwendet, da sie im Allgemeinen eine bessere Leistung erbringen, aber festplattenbasierte Tabellen unterstützen sie nicht, da sie die Leistung beeinträchtigen und keinen Bonus darstellen können. Es gibt nichts zu stoppen Hash - Indizes werden für Disk - basierten Tabellen natürlich zur Verfügung gestellt, zweifle nicht einige Datenbanken tun die diese Funktion unterstützen, aber vermutlich werden sie nicht in ISAM / InnoDB - Tabellen als Maintainer implementiert berücksichtigen nicht die Funktion noch hinzugefügt (wie die Zusätzlicher Code zum Schreiben und Verwalten ist unter den wenigen Umständen, die einen signifikanten Unterschied ausmachen, den Vorteil nicht wert. Wenn Sie dem nicht zustimmen, können Sie mit ihnen sprechen und sich für die Implementierung der Funktion einsetzen.
Wenn Sie große Zeichenfolgen indizieren, kann die Implementierung eines eigenen Pseudo-Hash-Index (durch Speichern eines Hashs des Werts sowie des tatsächlichen Werts und der Indizierung der Spalte) funktionieren, dies ist jedoch nur bei großen Zeichenfolgen (wo) definitiv effizienter Das Berechnen des Hash-Werts und das Durchsuchen des Baumindex anhand dieses Werts ist in der Regel schneller als das Durchsuchen eines Baumindex anhand der größeren Vergleichswerte, und der zusätzlich verwendete Speicher ist nicht signifikant.) Führen Sie daher vor der Implementierung eine Leistungsanalyse durch dies in der Produktion.
quelle
In einem verwandten Hinweis finden Sie möglicherweise die Diskussion über Indextypen in den PostgreSQL-Dokumenten interessant. Es ist in neueren Versionen der Dokumentation nicht mehr vorhanden (aufgrund späterer Optimierungen, nehme ich an), aber das Take-Away könnte für MySQL ähnlich sein (und der Grund, warum Hash-Indizes nur für Heap-Tabellen verwendet werden):
http://www.postgresql.org/docs/8.1/static/indexes-types.html
Auch hier handelt es sich um eine (veraltete) PostgreSQL-spezifische Version, die jedoch darauf hinweisen sollte, dass der "natürliche" Indextyp nicht unbedingt eine optimale Leistung erbringt.
quelle
Hier ist etwas Interessantes:
Gemäß dem Buch MySQL 5.0 Certification Study Guide , Seite 433, Abschnitt 29.5.1
Die MEMORY-Engine verwendet standardmäßig den Indexierungsalgorithmus HASH.
Zum Spaß habe ich versucht, mit HASH in MySQL 5.5.12 eine InnoDB-Tabelle und eine MyISAM-Tabelle mit einem Primärschlüssel zu erstellen
MySQL hat sich nicht beschwert.
AKTUALISIEREN
Schlechte Nachrichten !!! Ich habe SHOW INDEXES FROM verwendet. Es heißt, der Index ist BTREE.
Die CREATE INDEX-Syntax MySQL Page gibt an, dass nur MEMORY- und NDB-Speicher-Engines den HASH INDEX aufnehmen können.
Einige Leute schlugen vor, der Idee in den Seiten 102-105 des Buches " Hochleistungs-MySQL: Optimierungen, Backups, Replikation und mehr " zu folgen, um den Hash-Algorithmus zu emulieren.
Seite 105 enthält diesen Quick-and-Dirty-Algorithmus, den ich mag:
Machen Sie dazu eine Spalte in einer beliebigen Tabelle und indizieren Sie diesen Wert.
Versuche es !!!
quelle
BTree ist für die Suche nach einzelnen Zeilen nicht viel langsamer als Hash. Da BTree sehr effiziente Bereichsabfragen bietet, sollten Sie sich mit etwas anderem als BTree befassen.
Da MySQL BTree-Blöcke sehr gut zwischenspeichert, muss eine BTree-basierte Abfrage selten E / A-Vorgänge ausführen. Dies ist der höchste Zeitverbrauch in einer Abfrage.
quelle