Каковы ключевые различия между индексами B-Tree и Hash в PostgreSQL

Ответ

Основное различие заключается в их внутренней структуре и, как следствие, в сценариях использования. B-Tree является универсальным и используется по умолчанию, в то время как Hash-индекс оптимизирован для узкой задачи.

B-Tree (B-дерево)

Сбалансированная древовидная структура, которая хранит данные отсортированными. Это делает её эффективной для широкого спектра операций.

  • Лучше всего подходит для:
    • Запросов на точное совпадение (=).
    • Диапазонных запросов (>, <, BETWEEN).
    • Поиска по префиксу (LIKE 'prefix%').
    • Сортировки (ORDER BY).
  • Преимущества: Универсальность, поддержка всех типов данных, поддержка ограничений UNIQUE.

Hash (Хеш-индекс)

Хранит хеш-коды от индексируемых значений. Поиск происходит путем вычисления хеша и прямого доступа к соответствующей "корзине" данных.

  • Лучше всего подходит для:
    • Только запросов на точное совпадение (=).
  • Ограничения: Не поддерживает диапазонные запросы, сортировку или поиск по префиксу. До версии PostgreSQL 10 хеш-индексы не были транзакционно-безопасными и требовали ручной перестройки.

Пример создания:

-- B-Tree индекс (используется по умолчанию)
CREATE INDEX idx_users_email_btree ON users (email);

-- Hash индекс (нужно явно указать USING HASH)
CREATE INDEX idx_users_email_hash ON users USING HASH (email);

Вывод: На практике B-Tree используется в подавляющем большинстве случаев из-за своей гибкости. Hash может дать небольшое преимущество в производительности и размере для очень больших таблиц, где запросы выполняются исключительно на точное равенство.

Ответ 18+ 🔞

Давай разберем эту индексационную хрень, а то я вижу, у тебя глаза уже стекленеют. Слушай сюда, это же не просто так, это про то, как база данных не ебёт мозги при каждом запросе.

Представь, что у тебя есть список из миллиона пользователей в одной куче, и тебе надо найти Васю Пупкина. Без индекса — это пиздец, полный перебор, как искать иголку в стоге сена, который ещё и горит. А индекс — это такая хитрая шпаргалка, которая говорит: «Вася Пупкин, иди нахуй, он на странице 284, строка 15».

И вот этих шпаргалок бывает два основных вида, и они, блядь, как два разных инструмента: один — швейцарский нож, а второй — кувалда. И сейчас я тебе объясню, когда какую хуйню использовать.

B-Tree (или B-дерево, если по-пацански)

Это наш швейцарский армейский нож, универсальная хуйня, которую Postgres по умолчанию и использует. Устроено оно как сбалансированное дерево, где всё отсортировано по полю, которое ты проиндексировал.

  • Когда его пихать куда надо? Да почти всегда, сука! Он заточен под:
    • Точный поиск (WHERE email = 'vasyan@mail.ru').
    • Поиск по диапазону, типа «найди всех, кто родился с 1990 по 2000» (BETWEEN, >, <).
    • Поиск по началу слова, типа «все имена на "Ва"» (LIKE 'Ва%').
    • Сортировку результатов, чтобы не ждать, пока они там в пизду соберутся (ORDER BY).
  • В чём его сила? Он нихуя не теряет актуальность, работает со всеми типами данных, и на нём можно строить ограничения уникальности.

Hash (Хеш-индекс)

А вот это, дружок, наша кувалда. Очень простая, но тупая в хорошем смысле штука. Берёт значение (например, тот же email), пропускает его через хеш-функцию (получается какая-то цифровая каша), и по этому числу сразу знает, где лежит запись. Прямой доступ, нихуя лишнего.

  • Когда им огребать? Только в одной, блядь, ситуации:
    • ТОЧНОЕ СОВПАДЕНИЕ (=). Всё. Точка.
  • А в чём подвох? А подвох в том, что он нихуя не умеет:
    • Искать по диапазону? Не, не слышал.
    • Сортировать? Иди нахуй.
    • Искать по началу слова? Ты о чём вообще? Раньше (до 10-й версии Postgres) с ними была ещё одна засада — они могли накрыться медным тазом после сбоя, и их надо было перестраивать вручную. Сейчас вроде пофиксили, но осадочек-то остался.

Вот как эту всю хуйню на столбах развесить:

-- B-Tree — дефолтный, можно даже не писать USING BTREE, но для ясности можно
CREATE INDEX idx_users_email_btree ON users USING BTREE (email);

-- Hash — тут надо явно сказать, что мы хотим именно эту кувалду
CREATE INDEX idx_users_email_hash ON users USING HASH (email);

Итог, который тебе в сраку: В 99.9% случаев ты будешь тыкать B-Tree и будешь прав как никогда. Он покрывает все базовые потребности нормального человека. Hash — это такая узкая, ебанутая оптимизация для особых случаев, когда у тебя таблица размером с овердохуища, и ты с неё только и делаешь, что ищешь по точному совпадению. Во всех остальных случаях — это стрельба из пушки по воробушкам, только место на диске жрёт.