it-swarm.com.de

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

Für jede Version von Postgres, die Hash Indizierung unterstützt, gibt es eine Warnung oder einen Hinweis, dass Hash-Indizes "ähnlich oder" sind langsamer "oder" nicht besser "als btree Indizes, 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 zu 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 Erstellungszeit für Hash-Indizes ist 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. :

Hinweis: Tests haben gezeigt, dass die Hash-Indizes von PostgreSQL nicht besser sind 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. behaupten sie, dass sie nie einen Fall gefunden haben, 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!

8
Sampson Crowley

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), weil Konstanten in der großen O-Notation keine Rolle spielen, aber in der Realität eine Rolle spielen.

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.

7
jjanes

Die Hash-Suche ist theoretisch eine O(1) -Operation, wenn der Schlüssel-Hash direkt dem physischen Speicherort des Zieldatensatzes zugeordnet ist. Die Funktionsweise in Postgres ist, wenn ich es richtig verstehe, etwas komplizierter: Der Schlüssel-Hash wird einem Bucket zugeordnet, der das OID Sie suchen. 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 Hash-Index-Zugriffsmethode README-Datei im Quellcode-Repo enthält alle Details.

3
mustaccio