DBAtlas · Атлас эксплуатации баз данных

Медленный запрос: углублённая диагностика

Медленный запрос или вся система. Сужайте поиск шаг за шагом: выполняйте проверку в каждом узле и выбирайте ветку по результату. В конце получаете первопричину + исправление.

Что медленно?

Медленный один или несколько конкретных запросов или вся система? Это разделяет расследование на одно из двух направлений: 'запрос' или 'ресурсы/узкое место'.

  • Медленные один или несколько конкретных запросов
  • Медленная вся система

Выполняется ли запрос прямо сейчас?

Это запрос, который выполняется/завис прямо сейчас, или 'в целом медленный'? Посмотрите на активные сессии.

SELECT sid, serial#, sql_id, last_call_et AS running_sec, event, blocking_session
FROM v$session WHERE status='ACTIVE' AND type='USER' ORDER BY last_call_et DESC;
  • Выполняется / завис прямо сейчас
  • В целом медленный; хочу посмотреть его план

Ждёт ли запрос чего-то?

Если он активен, но не продвигается, скорее всего, он ждёт. Заполнены ли blocking_session / wait_event?

SELECT sid, blocking_session, event, seconds_in_wait
FROM v$session WHERE sid=&target_sid;
  • Заблокирован другой сессией
  • Ждёт ресурс (IO / журнал / latch)
  • Ожидания нет; активно расходует CPU

Какое ожидание преобладает?

Преобладающее событие ожидания указывает тип узкого места.

SELECT event, total_waits, time_waited FROM v$session_event WHERE sid=&target_sid ORDER BY time_waited DESC FETCH FIRST 5 ROWS ONLY;
  • Ожидание IO (db file read / PAGEIOLATCH)
  • Ожидание журнала / commit (log file sync / WRITELOG)
  • Блокировка / enqueue (enq: TX / LCK)

Получите план выполнения (EXPLAIN)

Получите план. Есть ли полное сканирование таблицы, неожиданный порядок соединений или разрыв между оценочным и фактическим числом строк?

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));
  • Полное сканирование / нет индекса
  • Вчера был быстрым; план внезапно изменился
  • Обрабатывает слишком много строк / N+1
  • План выглядит хорошо, но медленно

Актуальна ли статистика?

Большой разрыв между оценочным и фактическим числом строк (E-rows vs A-rows) — признак устаревшей статистики.

SELECT table_name, num_rows, last_analyzed FROM dba_tables WHERE table_name='&TABLE_NAME';
  • Статистика устарела
  • Статистика актуальна, но всё равно медленно

Вся система: где узкое место?

Если медленно всё, а не один запрос, ищите узкое место по ресурсам: CPU, IO, память или массовые блокировки?

SELECT metric_name, value FROM v$sysmetric WHERE metric_name IN ('Host CPU Utilization (%)','Average Active Sessions') AND intsize_csec=(SELECT MAX(intsize_csec) FROM v$sysmetric);
  • CPU близок к 100%
  • Высокое ожидание IO
  • Давление на память / низкий процент попаданий в кэш
  • Много блокировок

Первопричина: блокировки

Запрос ждёт блокировку, удерживаемую другой сессией. Найдите сессию во главе цепочки (корневой блокировщик) и устраните её.

Первопричина: узкое место IO

Запрос много читает с диска. Обычно из-за полных сканирований (нет индекса) или нехватки памяти (буферный кэш).

Первопричина: узкое место commit / журнала

Если преобладает 'log file sync' / 'WRITELOG', фиксации ждут записи redo/WAL.

Первопричина: нет индекса

План выполняет полное сканирование. Подходящий индекс по столбцам фильтра/соединения даёт большое ускорение.

Первопричина: регрессия плана

Вчера запрос был быстрым, а сегодня нет; план изменился. Обычно из-за устаревшей статистики или изменения параметров.

Первопричина: дизайн запроса

План разумен, но запрос по своей сути делает слишком много работы (слишком много строк, N+1, лишние соединения).

Первопричина: устаревшая статистика

Оптимизатор ошибается в оценках, потому что статистика не актуальна.

Углублённый анализ

Если план и статистика в порядке, но всё равно медленно, копайте глубже.

Первопричина: узкое место CPU

Вся система упирается в CPU. Обычно CPU сжигают несколько запросов с плохими планами.

Первопричина: давление на память

Низкий процент попаданий в кэш и/или своппинг: памяти недостаточно или она распределена неправильно.

Открыть в DBAtlas →