> Индексы замедляют или ускоряют чтение и запись в базе данных (Go)

Уровень: middle · Роль: backend · Категория: Технические вопросы

Компании: Сбер

Стек: Go

> Пример ответа

Короткий ответ

Индексы ускоряют чтение, но замедляют запись. При чтении индекс позволяет найти данные за O(log n) вместо полного сканирования таблицы. При записи (INSERT, UPDATE, DELETE) приходится обновлять не только саму строку, но и все индексы, которые её содержат, - это дополнительные операции записи и перестроения B-tree. Точный trade-off зависит от соотношения чтений и записей в конкретном приложении.

Подробное объяснение

Индекс - это отдельная структура данных (обычно B-tree или hash), которая хранит отсортированные значения ключей и ссылки на строки таблицы. Она позволяет СУБД не сканировать всю таблицу, а сразу перейти к нужному диапазону значений.

Влияние на чтение:

  • Ускоряет точечные запросы (WHERE id = 5) и диапазонные (WHERE created_at BETWEEN ...)
  • Ускоряет JOIN, ORDER BY, GROUP BY, если индексы покрывают используемые колонки
  • Позволяет использовать index-only scan, когда все нужные колонки есть в самом индексе - тогда таблица вообще не читается

Влияние на запись:

  • Каждый INSERT добавляет запись во все индексы таблицы
  • Каждый UPDATE, меняющий индексированную колонку, требует удаления старой записи из индекса и вставки новой
  • DELETE удаляет записи из всех индексов
  • При переполнении страниц B-tree может происходить split - операция дороже, чем просто вставка

Косвенные эффекты:

  • Индексы увеличивают размер базы данных на диске
  • Больше индексов - больше кэш-промахов при чтении страниц индекса
  • В PostgreSQL каждый индекс - это отдельная структура, в MySQL InnoDB вторичные индексы хранят primary key, что добавляет ещё один lookup

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

  • Если таблица маленькая и индекс целиком помещается в память
  • Если запись идёт в конец таблицы (append-only) и индекс монотонно возрастает - вставка в B-tree происходит без split

На практике

  • Индексируйте только те колонки, которые реально используются в WHERE, JOIN, ORDER BY
  • Не создавайте индексы "на всякий случай" - каждый лишний индекс платит за каждую запись
  • Для high-write систем (логи, события, метрики) часто выгоднее не индексировать ничего, кроме primary key
  • Для read-heavy систем (каталоги, справочники) индексы почти всегда оправданы
  • Составной индекс на (a, b) покрывает запросы по a и по (a, b), но не по b - учитывайте порядок колонок
  • Используйте EXPLAIN в PostgreSQL или EXPLAIN ANALYZE в MySQL, чтобы увидеть, использует ли запрос индекс на самом деле
  • В PostgreSQL есть partial index (WHERE status = 'active') и covering index (INCLUDE) - они уменьшают стоимость записи, потому что индексируют только часть строк или хранят дополнительные колонки без включения их в дерево

Пример кода

SQL
-- Создание индекса
CREATE INDEX idx_users_email ON users (email);
-- Составной индекс
CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);
-- Partial index в PostgreSQL - индексируем только активные заказы
CREATE INDEX idx_orders_active ON orders (created_at) WHERE status = 'active';
-- Covering index - храним колонку без участия в поиске
CREATE INDEX idx_users_email_name ON users (email) INCLUDE (name);
-- Проверка плана запроса
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

Как отвечать на собеседовании

Начните с прямого ответа: чтение ускоряют, запись замедляют. Затем объясните механику: B-tree, необходимость обновления структуры при каждой модификации. Приведите конкретный пример из практики: например, таблица логов с индексом по timestamp - запись замедлится, но выборки по времени станут быстрее. Упомяните, что в реальных системах решение принимается на основе профиля нагрузки: если 95% операций - чтение, индексы почти всегда нужны; если 50/50 - нужно считать. Если спросят про конкретную СУБД, уточните: в PostgreSQL индексы не блокируют запись (MVCC), но добавляют I/O; в MySQL InnoDB вторичные индексы содержат primary key, что влияет на размер.

Что проверяет интервьюер

  • Понимание внутреннего устройства индекса (B-tree, hash)
  • Умение рассуждать о trade-off между скоростью чтения и стоимостью записи
  • Знание, что индекс - это не "бесплатное ускорение", а структура с накладными расходами
  • Понимание разницы между типами индексов (covering, partial, composite)
  • Умение применять знания на практике: когда индекс нужен, а когда вреден
  • Наличие реального опыта: кандидат должен упомянуть случаи, когда индекс не помог или замедлил запись

Типичные ошибки

  • Ответ "индексы ускоряют всё" - неверно, запись страдает
  • Утверждение "индекс всегда ускоряет чтение" - на маленьких таблицах полное сканирование быстрее, чем чтение индекса + таблицы
  • Игнорирование того, что UPDATE, меняющий индексированную колонку, стоит дороже, чем UPDATE неиндексированной
  • Предложение индексировать все колонки "для скорости" - это антипаттерн
  • Непонимание, что составной индекс работает только для префикса колонок
  • Забывают про overhead на хранение индекса: на больших таблицах индекс может занимать больше места, чем сами данные

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью