Почему нельзя использовать Hash-индекс везде в базах данных

Ответ

Hash-индексы оптимальны только для операций точного совпадения (=), но имеют серьёзные ограничения:

Ограничения Hash-индексов:

  1. Не поддерживают диапазонные запросы

    -- Hash-индекс НЕ поможет
    SELECT * FROM orders WHERE total_amount > 1000;
    SELECT * FROM users WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';
  2. Не поддерживают сортировку (ORDER BY)

    -- Неэффективно с Hash-индексом
    SELECT * FROM products ORDER BY price DESC;
  3. Не поддерживают поиск по префиксу

    -- Hash-индекс бесполезен
    SELECT * FROM articles WHERE title LIKE 'PHP%';
  4. Только операции равенства — Hash-индекс вычисляет хэш-значение, поэтому WHERE id = 5 работает быстро, но WHERE id > 5 — нет.

Практический пример из PostgreSQL:

-- Создаём Hash-индекс для точного поиска по email
CREATE INDEX idx_users_email_hash ON users USING hash(email);

-- Эффективный запрос
SELECT * FROM users WHERE email = 'alice@example.com';

-- Для этих запросов нужен B-tree индекс
CREATE INDEX idx_users_created_btree ON users(created_at);
SELECT * FROM users WHERE created_at > '2024-01-01' ORDER BY created_at;

Когда использовать Hash-индекс:

  • Таблицы поиска (lookup tables) с уникальными значениями
  • Частые запросы с = без сортировки
  • Когда данные часто обновляются (в некоторых СУБД Hash эффективнее для вставок)

В MySQL InnoDB Hash-индексы используются автоматически для адаптивного хэширования, но явно создать Hash-индекс нельзя.

Ответ 18+ 🔞

А, слушай, про эти hash-индексы расскажу, а то народ часто нихуя не понимает, где их пихать. Представь себе, будто у тебя есть супербыстрый справочник, но только для одного вопроса: «А где тут Вася?». И всё. Больше нихуя.

В чём их подвох, ёпта:

  1. Про диапазоны забудь как страшный сон

    -- С этим hash-индекс накроется медным тазом сразу
    SELECT * FROM orders WHERE total_amount > 1000;
    SELECT * FROM users WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';

    Ему похуй на «больше» или «между». Он тупо хэш считает и ищет полное совпадение. Всё остальное — пиздец и полный перебор.

  2. Сортировку (ORDER BY) не потянет

    -- Запрос будет тормозить, как мартышка на льду
    SELECT * FROM products ORDER BY price DESC;

    Потому что данные в нём разбросаны, как говно по тайге — никакой логической последовательности. Для сортировки нужен другой урод.

  3. Поиск «начинается с...» — не его история

    -- Hash-индекс тут просто пизда рулю
    SELECT * FROM articles WHERE title LIKE 'PHP%';

    Он же не строки сравнивает, а хэши. «PHP%» и «PHQ%» — для него это вообще разные вселенные, ядрёна вошь.

  4. Равенство — его единственная фишка Вот где он охуенно быстр: WHERE id = 5. Вычислил хэш от пятёрки — бац, и сразу адрес записи. А попроси WHERE id > 5 — и он просто охуеет и пойдёт читать всю таблицу.

Пример из реальности, на PostgreSQL:

-- Делаем hash-индекс для почты, если ищем только по полному совпадению
CREATE INDEX idx_users_email_hash ON users USING hash(email);

-- Запрос летает, как угорелый
SELECT * FROM users WHERE email = 'alice@example.com';

-- А для вот этого нужен уже B-tree, иначе будет пиздец
CREATE INDEX idx_users_created_btree ON users(created_at);
SELECT * FROM users WHERE created_at > '2024-01-01' ORDER BY created_at;

Так когда же его впендюрить?

  • Для всяких справочников, где ключ уникальный и ищется только по =.
  • Когда тебе похуй на сортировки и диапазоны — только точный поиск.
  • Иногда для часто обновляемых данных (зависит от СУБД, там свои заморочки).

Кстати, в MySQL InnoDB ты явно hash-индекс не создашь — там эта штука внутри работает как адаптивное хэширование, само решает, где его применить. Так что не пытайся, чувак, это бесполезно.