Wie ist es möglich, dass der Hash-Index für Gleichstellungssuchen nicht schneller als Btree ist?


8

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:

Version 7.2 :

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.

Version 7.3 (und bis 8.2) :

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.

Version 8.3 :

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!


Antworten:


7

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.


Vielen Dank. Ich bin mir sehr bewusst, wie weit diese Versionen nach ihrem Ablaufdatum liegen, aber ich war immer noch neugierig, wie weit die Leistung hinter dem zurückblieb, was ich erwartet hätte
Sampson Crowley

3

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.


Im Grunde genommen ist ein Hash-Index eine Art Verzweigungsindex für psql
Sampson Crowley,

das macht tatsächlich viel mehr Sinn zu wissen, dass sie Eimer verwenden, um die tatsächlichen Schlüssel zu speichern
Sampson Crowley

Danke auch für den Link zur Readme. Ich hatte keine Ahnung, dass diese im Repo existierten
Sampson Crowley

2
Die Überlaufseiten müssen linear durchsucht werden, und im schlimmsten Fall kann es zu einer unbegrenzten Anzahl von Seiten kommen. Die Suchvorgänge innerhalb einer Seite haben jedoch eine begrenzte Anzahl von Elementen, die auf einer Seite vorhanden sein können, sodass sie O (1) pro Überlaufseite sind, und sie verwenden eine binäre Suche, damit die Konstante auch nicht zu schäbig ist. Es war wirklich die Bestimmung, die Parallelität von Vorgängen sicher zu machen, die den Engpass darstellte.
jjanes

1
@AnoE - Sie werden überrascht sein ... Es gibt immer einen Kompromiss zwischen Leistung und [Verschwendung von] Ressourcen; In einigen Fällen kann man die Leistung bevorzugen.
Mustaccio
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.