Пример ответа
1) Короткий ответ
Оптимизатор может отказаться от индексов когда последовательное сканирование (Sequential Scan) оказывается дешевле индексного доступа, обычно при обработке большей части таблицы, на маленьких таблицах, или когда индексы не селективны.
2) Основные случаи отказа от индексов:
* Низкая селективность индекса:
* Запросы возвращают >15-20% строк таблицы
* Пример: WHERE status IN ('active', 'pending', 'completed')
при 3-х статусах
* Отсутствие статистики или устаревшая статистика:
* Оптимизатор не может оценить эффективность индекса
* После массовых операций UPDATE/DELETE
* Неоптимальный составной индекс:
* Порядок колонок в индексе не соответствует фильтрам
* Пример: Индекс на (category, date) для запроса WHERE date > '2024-01-01'
3) Конкретные сценарии с примерами:
Сценарий 1: Полное сканирование выгоднее индексного
```sql
-- При 1 млн строк, 800K имеют status = 'active'
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'active';
-- Решение: Seq Scan (последовательное чтение)
-- Seq Scan on orders (cost=0.00..15406.00 rows=800000 width=136)
```
Сценарий 2: Неиспользование индекса из-за функций
```sql
-- Индекс на created_at не будет использован
SELECT * FROM events
WHERE DATE(created_at) = '2024-01-15';
-- Оптимизированная версия использует индекс
SELECT * FROM events
WHERE created_at >= '2024-01-15' AND created_at < '2024-01-16';
```
4) Сравнение стоимостей доступа:
* Index Scan:
* Стоимость: Random I/O + чтение таблицы по pointers
* Эффективно: При малом % строк, сортировках, точечных запросах
* Sequential Scan:
* Стоимость: Sequential I/O по всей таблице
* Эффективно: При большом % строк, полных агрегациях
Рекомендация: Создавайте индексы на высокоселективных колонках, обновляйте статистику, используйте покрывающие индексы (INCLUDE).
5) Диагностика и решение проблем:
Анализ использования индексов:
```sql
-- Статистика использования индексов в PostgreSQL
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- Неиспользуемые индексы
-- Принудительное использование индекса (только для тестирования)
SET ENABLE_SEQSCAN = OFF;
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'active';
```
6) Follow-up вопросы:
* Как заставить оптимизатор использовать индекс?
* Ответ: Переписать запрос, создать покрывающий индекс, обновить статистику
* Что такое "index skip scan"?
* Ответ: Обход составного индекса когда префиксные колонки не в фильтрах
7) Практический совет (2 шага на неделю):
1. Проанализируйте планы запросов: Найдите 3 самых частых запроса с Seq Scan и проверьте возможность оптимизации через индексы.
2. Очистите неиспользуемые индексы: Выявите и удалите индексы с idx_scan = 0 для снижения overhead на запись.