Как ответить
Индексы в базах данных — это вспомогательные структуры, которые ускоряют операции поиска, фильтрации и сортировки. По сути это копия части данных, упорядоченная для быстрого доступа. За это приходится платить дополнительным местом на диске и замедлением записей, потому что индекс нужно обновлять при каждом INSERT, UPDATE или DELETE.
Самый распространённый тип — B-tree (или его вариация B+ tree). Работает для равенства (=) и диапазонов (<, >, BETWEEN). Например, поиск пользователя по email:
CREATE INDEX idx_users_email ON users(email);
SELECT * FROM users WHERE email = 'test@example.com';
Без индекса база будет делать полное сканирование таблицы — читать все строки. С индексом поиск идёт по дереву, сложность O(log N), а не O(N). Для миллиона записей это разница в сотни раз.
Есть и другие типы:
- Hash-индекс — только для точного сравнения, очень быстрый, но не поддерживает диапазоны. Используется редко, например в PostgreSQL при явном указании.
- GiST и GIN — для полнотекстового поиска, JSONB, массивов. В PostgreSQL GIN хорошо работает с jsonb и tsvector.
- Full-text — отдельный тип для текстового поиска, но чаще это функциональные индексы с to_tsvector.
На практике чаще всего работаешь с B-tree. Важно понимать композитные индексы — на несколько колонок. Порядок колонок имеет значение: индекс на (a, b) эффективен для фильтрации по a, по a и b вместе, для ORDER BY a, b, но не для фильтрации только по b. Если часто делаешь запросы с WHERE b = ? и WHERE a = ?, лучше создать два отдельных индекса.
Ещё одна оптимизация — covering index (индекс с покрытием), когда все нужные колонки запроса есть в самом индексе. Тогда база может вообще не обращаться к таблице — только к индексу. Это видно в EXPLAIN ANALYZE как «Index Only Scan».
Не стоит ставить индексы на всё подряд. На маленьких таблицах (до нескольких тысяч строк) полное сканирование может быть быстрее из-за накладных расходов. На колонках с низкой селективностью (пол, статус на два значения) индекс почти не поможет, потому что база всё равно прочитает много строк. И на таблицах с очень частыми вставками каждый лишний индекс снижает производительность.
Иногда индексы нужно обслуживать: в PostgreSQL есть REINDEX для устранения фрагментации, в MySQL — OPTIMIZE TABLE. План запроса — основной инструмент для проверки, используются ли индексы. EXPLAIN (ANALYZE, BUFFERS) показал, что запрос читает все строки? Значит, нужен индекс.