Как может Hash Index не быть быстрее, чем Btree для поиска на равенство?

8

Для каждой версии Postgres, которая поддерживает индексирование хеша , есть предупреждение или примечание, что хеш-индексы «похожи или медленнее» или «не лучше», чем индексы btree , по крайней мере, до версии 8.3. Из документов:

Версия 7.2 :

Примечание. Из-за ограниченной полезности хеш-индексов индекс B-дерева обычно предпочтительнее хеш-индекса. У нас нет достаточных доказательств того, что хеш-индексы на самом деле быстрее, чем B-деревья, даже для сравнений. Кроме того, хэш-индексы требуют более грубых блокировок; см. раздел 9.7.

Версия 7.3 (и до 8.2) :

Примечание. Тестирование показало, что хеш-индексы PostgreSQL аналогичны или медленнее, чем индексы B-дерева, а размер и время построения хеш-индексов намного хуже. Хэш-индексы также страдают от низкой производительности при высоком параллелизме. По этим причинам использование хеш-индекса не рекомендуется.

Версия 8.3 :

Примечание. Тестирование показало, что хеш-индексы PostgreSQL работают не лучше, чем индексы B-дерева, а размер и время построения хеш-индексов намного хуже. Кроме того, операции с хеш-индексами в настоящее время не регистрируются в WAL, поэтому, возможно, потребуется перестроить хеш-индексы с помощью REINDEX после сбоя базы данных. По этим причинам использование хеш-индекса в настоящее время не рекомендуется.

В этом потоке версии 8.0 они утверждают, что никогда не находили случая, когда хеш-индексы были на самом деле быстрее, чем btree.

Даже в версии 9.2 прирост производительности для чего-либо, кроме написания фактического индекса, был почти ничем, согласно этому сообщению в блоге (14 марта 2016 г.):
хэш-индексы на Postgres от Андре Барбоса.

Мой вопрос, как это возможно?

По определению хеш-индексы - это O(1)операция, где btree - это O(log n)операция. Так как же возможно, чтобы O(1)поиск был медленнее (или даже похож) на поиск правильной ветви и затем нахождение правильной записи?

Я хочу знать, что теория индексирования могла бы когда-либо сделать такую ​​возможность!

Сэмпсон Кроули
источник
Обсуждение перешло в чат .
ypercubeᵀᴹ

Ответы:

7

Дисковые индексы Btree на самом деле равны O (log N), но это не очень важно для дисковых массивов, которые подходят для этой солнечной системы. Из-за кэширования они в основном O (1) с очень большой константой плюс O ((log N) -1) с небольшой константой. Формально это то же самое, что O (log N), потому что константы не имеют значения в больших обозначениях O. Но они имеют значение в реальности.

Большая часть замедления поиска в хэш-индексе была вызвана необходимостью защиты от повреждения или взаимных блокировок, вызванных изменением размера хэш-таблицы одновременно с поиском. До недавних версий (каждая упомянутая вами версия устарела) эта потребность приводила к еще более высоким константам и довольно слабому параллелизму. Значительно больше человеко-часов ушло на оптимизацию параллелизма BTree, чем на хэш-параллелизм.

jjanes
источник
Спасибо. Я очень хорошо знаю, как далеко истек срок годности этих версий, но мне все еще было любопытно, насколько производительность отстала от того, что я ожидал
Сэмпсон Кроули,
3

Теоретически поиск хеша - это O(1)операция, когда хеш ключа отображается непосредственно на физическое местоположение целевой записи. То, как это работает в Postgres, если я правильно понимаю, немного сложнее: хэш ключа отображается в корзину, которая содержит искомый OID. Сегмент может содержать более одной страницы, которую необходимо последовательно сканировать, пока вы не найдете свой конкретный ключ (хеш). Вот почему это выглядит медленнее, чем вы ожидаете.

Файл README метода доступа к хэш-индексу в репозитории с исходным кодом содержит все подробности.

mustaccio
источник
так что в основном хеш-индекс - это тип индекса ветвления, что касается psql
Сэмпсон Кроули,
это действительно имеет больше смысла, зная, что они используют ведра для хранения реальных ключей
Сэмпсон Кроули,
Также спасибо за ссылку на readme. Я понятия не имел, что существовало в репо
Сэмпсон Кроули
2
Страницы переполнения нужно искать линейно, и в вырожденных случаях в худшем случае их может быть неограниченное количество. Но поиски на странице имеют ограниченное количество элементов, которые могут существовать на странице, поэтому они равны O (1) на страницу переполнения, и они используют двоичный поиск, так что константа также не слишком ветхая. Узким местом было обеспечение безопасности параллелизма операций.
Джанес
1
@AnoE - вы будете удивлены ... Всегда есть компромисс между производительностью и [растратой] ресурсов; в некоторых случаях можно отдать предпочтение производительности.
Мустаччо