Für jede Version von Postgres, die die Hash- Indizierung unterstützt, gibt es eine Warnung oder einen Hinweis, dass Hash-Indizes "ähnlich oder langsamer" oder "nicht besser" als btree- Indizes sind, zumindest bis Version 8.3. Aus den Dokumenten:
Hinweis: Aufgrund der eingeschränkten Nützlichkeit von Hash-Indizes sollte ein B-Tree-Index im Allgemeinen einem Hash-Index vorgezogen werden. Wir haben nicht genügend Beweise dafür, dass Hash-Indizes tatsächlich schneller sind als B-Bäume, selbst für Vergleiche. Darüber hinaus erfordern Hash-Indizes gröbere Sperren. siehe Abschnitt 9.7.
Hinweis: Tests haben gezeigt, dass die Hash-Indizes von PostgreSQL ähnlich oder langsamer sind als die B-Tree-Indizes, und die Indexgröße und die Erstellungszeit für Hash-Indizes sind viel schlechter. Hash-Indizes leiden auch unter einer schlechten Leistung bei hoher Parallelität. Aus diesen Gründen wird von der Verwendung von Hash-Indizes abgeraten.
Hinweis: Tests haben gezeigt, dass die Hash-Indizes von PostgreSQL nicht besser abschneiden als B-Tree-Indizes, und die Indexgröße und Erstellungszeit für Hash-Indizes ist viel schlechter. Darüber hinaus werden Hash-Index-Operationen derzeit nicht WAL-protokolliert, sodass Hash-Indizes nach einem Datenbankabsturz möglicherweise mit REINDEX neu erstellt werden müssen. Aus diesen Gründen wird derzeit von der Verwendung von Hash-Indizes abgeraten.
In diesem Thread der Version 8.0 wird behauptet, dass noch nie ein Fall gefunden wurde, in dem Hash-Indizes tatsächlich schneller als btree waren.
Selbst in Version 9.2 war der Leistungsgewinn für etwas anderes als das Schreiben des tatsächlichen Index laut diesem Blog-Beitrag (14. März 2016) fast nichts:
Hash-Indizes auf Postgres von André Barbosa.
Meine Frage ist, wie ist das möglich?
Per Definition sind Hash-Indizes eine O(1)
Operation, wobei ein btree eine O(log n)
Operation ist. Wie ist es also möglich, dass eine O(1)
Suche langsamer ist als (oder sogar ähnlich) das Finden des richtigen Zweigs und dann das Finden des richtigen Datensatzes?
Ich möchte wissen, was mit der Indizierungstheorie jemals eine Möglichkeit machen könnte!
quelle
Antworten:
Festplattenbasierte Btree-Indizes sind tatsächlich O (log N), aber das ist für Festplatten-Arrays, die in dieses Sonnensystem passen, ziemlich irrelevant. Aufgrund des Caching sind sie meistens O (1) mit einer sehr großen Konstante plus O ((log N) -1) mit einer kleinen Konstante. Formal ist das dasselbe wie O (log N), da Konstanten in der großen O-Notation keine Rolle spielen. Aber sie sind in Wirklichkeit wichtig.
Ein Großteil der Verlangsamung bei der Suche nach Hash-Indizes resultierte aus der Notwendigkeit, sich vor Korruption oder Deadlocks zu schützen, die durch die Größenänderung von Hash-Tabellen gleichzeitig mit den Lookups verursacht wurden. Bis zu den neuesten Versionen (jede Version, die Sie erwähnen, ist komisch veraltet) führte dies zu noch höheren Konstanten und zu einer eher schlechten Parallelität. Für die Optimierung der BTree-Parallelität wurden erheblich mehr Arbeitsstunden aufgewendet als für die Hash-Parallelität.
quelle
Die Hash-Suche ist theoretisch eine
O(1)
Operation, bei der der Schlüssel-Hash direkt dem physischen Speicherort des Zieldatensatzes zugeordnet wird. Die Art und Weise, wie es in Postgres funktioniert, ist, wenn ich es richtig verstehe, etwas komplizierter: Der Schlüssel-Hash wird einem Bucket zugeordnet , der die gesuchte OID enthält. Ein Bucket kann möglicherweise mehr als eine Seite umfassen, die Sie nacheinander scannen müssen, bis Sie Ihren bestimmten Schlüssel (Hash) gefunden haben. Aus diesem Grund erscheint es langsamer als erwartet.Die README-Datei der Hash-Index-Zugriffsmethode im Quellcode-Repo enthält alle Details.
quelle