Ответ
Плюсы индексов:
- Кардинальное ускорение операций поиска (
SELECT ... WHERE). Без индекса СУБД выполняет полное сканирование таблицы (FULL TABLE SCAN). Индекс, особенно B-дерево, позволяет найти данные за логарифмическое время. - Ускорение операций соединения (
JOIN). Индексы на полях связи (foreign keys) критически важны для производительности JOIN. - Ускорение сортировки (
ORDER BY) и группировки (GROUP BY). Если индекс построен по полям сортировки, данные уже можно считать в нужном порядке. - Обеспечение уникальности. Уникальный индекс (
UNIQUE) гарантирует целостность данных на уровне БД. - Ускорение агрегатных функций (
MIN(),MAX()) для индексированных полей.
Минусы и затраты:
- Дополнительное дисковое пространство. Индекс — это отдельная структура данных. Для больших таблиц размер индекса может быть сопоставим с размером самой таблицы.
- Замедление операций записи (
INSERT,UPDATE,DELETE). При каждой модификации данных СУБД должна обновлять все affected индексы. Это основная цена за ускорение чтения. - Избыточные индексы ухудшают производительность. Неиспользуемые или дублирующие индексы тратят ресурсы на обновление и могут сбивать с толку оптимизатор запросов.
- Сложность выбора. Неправильно составленный индекс (например, индекс с плохой селективностью или в неправильном порядке полей) может не использоваться.
Практический пример из моего опыта (MySQL):
-- Создание составного индекса. Порядок полей ВАЖЕН!
-- Этот индекс поможет для запросов с условиями по country, а также по country + city.
CREATE INDEX idx_location ON users(country, city);
-- Запрос, который использует индекс эффективно:
SELECT * FROM users WHERE country = 'Germany' AND city = 'Berlin'; -- Использует idx_location
-- Запрос, который, скорее всего, НЕ использует этот индекс (или использует неэффективно):
SELECT * FROM users WHERE city = 'Berlin'; -- Индекс не может быть использован, т.к. city не первое поле
Мои best practices:
- Индексирую поля, часто используемые в
WHERE,JOIN,ORDER BY. - Для текстовых поисков по подстроке (
LIKE '%pattern%') стандартные индексы бесполезны, рассматриваю полнотекстовый поиск. - Регулярно анализирую медленные запросы с помощью
EXPLAINиSlow Query Log. - Удаляю неиспользуемые индексы. В MySQL можно включить
performance_schemaдля сбора статистики использования. - Помню, что иногда один хорошо составленный составной индекс лучше нескольких одиночных.