Ключевое слово `EXPLAIN` перед SQL-запросом позволяет получить детальную информацию о том, как PostgreSQL **планирует** выполнить этот запрос "под капотом". Это полезно для диагностики производительности, поскольку помогает понять, какие шаги выполняет база данных и где могут быть узкие места.
Пример использования `EXPLAIN`
```sql
postgres=# EXPLAIN SELECT * FROM users WHERE id = 20;
Index Scan using users_pkey on users (cost=0.15..8.17 rows=1 width=72)
Index Cond: (id = 20)
(2 rows)
```
Вывод информации можно изменить. Например, чтобы получить результат в формате JSON:
```sql
EXPLAIN (FORMAT JSON) SELECT * FROM users WHERE id = 20;
```
> [!NOTE] Analyze
> `EXPLAIN` не выполняет сам запрос, поэтому результаты будут приблизительными. Для более точного анализа можно добавить ключевое слово `ANALYZE`, и тогда `EXPLAIN` также выполнит запрос.
PostgreSQL использует условные единицы для обозначения стоимости выполнения запроса — `cost`. Один `cost` примерно соответствует времени, затраченному на извлечение одной [[../DB page|страницы]] при последовательном сканировании (Seq Scan).
- **Первое значение**: стоимость до начала получения первых результатов.
- **Второе значение**: полная стоимость выполнения запроса.
Если оценочное значение `rows` слишком низкое по сравнению с фактическим количеством строк, это может означать, что статистика таблицы устарела. В таком случае необходимо выполнить `ANALYZE` для обновления статистики и улучшения качества планирования запросов.
Также PostgreSQL умеет считать количество обращений к диску. Для этого нужно добавить опцию `buffres`: `explain (analize, buffres)`. Это не время на чтение, а количества чтений.
- **Seq Scan**: последовательный просмотр всей таблицы. Это наиболее медленный вариант и обычно нежелателен. Решение — добавить [[../Индекс базы данных|индекс]], чтобы ускорить выборку данных.
- **Index Scan**: использование [[../Индекс базы данных|индекса]] для просмотра таблицы.
- **Index Only Scan**: использование [[../Покрывающий индекс|покрывающего индекса]], когда все нужные данные находятся в индексе и не требуется дополнительного доступа к таблице.
- **Bitmap Heap Scan**: оптимизация с использованием битовых карт для поиска. Сначала строятся битовые карты с использованием нескольких индексов, затем они комбинируются.
- **Foreign Scan**: сканирование данных на удаленном сервере, используемое при [[Шардирование в PostgreSQL|шардировании]].