ПрограммированиеSQL/Database разработчик

Опишите работу индексов в SQL. Как они ускоряют запросы, и в каких случаях их использование может, наоборот, замедлить систему?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Индексы — специальные структуры данных (чаще всего на основе B-деревьев), служащие для быстрого поиска данных по определённому столбцу или набору столбцов таблицы. Индексы ускоряют выборку, сортировку и фильтрацию, уменьшая количество просматриваемых строк.

Типы индексов:

  • Обычные (B-tree, hash)
  • Составные (мультиколоночные)
  • Уникальные (обеспечивают уникальность значений)
  • Покрывающие (covering)
  • Полнотекстовые (full-text)

Индексы ускоряют:

  • WHERE ... = ...
  • JOIN по индексированному столбцу
  • ORDER BY и GROUP BY по индексированному столбцу

Могут замедлить:

  • Вставка, обновление, удаление — индексы требуют дополнительных операций для поддержания своей структуры.
  • Если запросы часто используют столбцы, по которым нет индексов, индексы будут бесполезны, а при массовых вставках — даже вредны.

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

CREATE INDEX idx_user_email ON users (email);

Пример, где индекс не помогает:

SELECT * FROM users WHERE lower(email) = 'test@example.com'; -- если индекс построен на email, но запрос использует функцию lower(email), индекс не используется!

Вопрос с подвохом

Если добавить индекс ко всем столбцам таблицы, всегда ли ускорится выполнение всех SELECT-запросов?

Ответ:
Нет. Индексы ускоряют только те запросы, где фильтрация или сортировка происходит строго по индексированному столбцу без применения функций или операций, препятствующих использованию индекса. Чрезмерное количество индексов не только замедляет INSERT/UPDATE/DELETE, но и занимает много места, а некоторые сложные запросы могут и вовсе обходить индексы (например, при сканировании по диапазону с выражением).

Пример:

SELECT * FROM orders WHERE year(order_date) = 2023; -- если индекс только на order_date, индекс не работает из-за функции year()

История

В электронной почтовой системе был создан триггер, который создавал индекс для каждого часто используемого поля. Через полгода производительность системы упала — на каждую вставку или изменение строки тратилось в 4-5 раз больше времени. После аудита количество индексов сократили, система ускорилась.


История

В рекламной платформе часто встречались запросы SELECT с фильтром по substring(url, 1, 10). Несмотря на индекс по url, SQL не задействовал индекс из-за функции substring. Решением стало введение отдельного поля для такой выборки и индекс по нему.


История

В программе лояльности был создан составной индекс на поля (customer_id, shop_id). При запросах только по shop_id индекс не применялся, и происходил полный скан таблицы (full scan). Это привело к утрате выгоды от индекса при расчетах бонусов. Помогла оптимизация: отдельный индекс по shop_id.