Найти топ SQL по затраченному времени/CPU за прошлый период (AWR + V$SQLAREA)
OracleПроизводительностьКоманда
-- AWR: top 20 by elapsed time within a snapshot range (per plan)
SELECT *
FROM (SELECT st.sql_id,
st.plan_hash_value,
SUM(st.executions_delta) AS execs,
ROUND(SUM(st.elapsed_time_delta)/1e6, 1) AS elapsed_s,
ROUND(SUM(st.cpu_time_delta)/1e6, 1) AS cpu_s,
ROUND(SUM(st.iowait_delta)/1e6, 1) AS io_wait_s,
SUM(st.buffer_gets_delta) AS buffer_gets,
ROUND(SUM(st.elapsed_time_delta)/1e3
/ NULLIF(SUM(st.executions_delta),0), 2) AS ms_per_exec,
MAX(st.parsing_schema_name) AS parsing_schema
FROM dba_hist_sqlstat st
WHERE st.dbid = (SELECT dbid FROM v$database)
AND st.snap_id BETWEEN <begin_snap> AND <end_snap>
GROUP BY st.sql_id, st.plan_hash_value
ORDER BY elapsed_s DESC)
WHERE ROWNUM <= 20;
-- For CPU ranking: ORDER BY cpu_s DESC
-- SQL text: SELECT DBMS_LOB.SUBSTR(sql_text, 4000, 1) FROM dba_hist_sqltext WHERE sql_id = '<sql_id>';
-- Plan history of a single SQL: @?/rdbms/admin/awrsqrpt.sql
-- Current (since instance startup, still in cache) by CPU:
SELECT sql_id,
ROUND(cpu_time/1e6,1) AS cpu_s,
ROUND(elapsed_time/1e6,1) AS elapsed_s,
executions, buffer_gets, disk_reads,
ROUND(cpu_time/1e3/NULLIF(executions,0),2) AS cpu_ms_per_exec,
parsing_schema_name,
SUBSTR(sql_text,1,80) AS sql_text
FROM v$sqlarea
WHERE parsing_schema_name NOT IN ('SYS','SYSTEM')
ORDER BY cpu_time DESC
FETCH FIRST 20 ROWS ONLY;Что делает
Суммирует столбцы *_DELTA в DBA_HIST_SQLSTAT, чтобы вывести самые дорогие SQL в диапазоне снимков с разбивкой по plan_hash_value, что также выявляет смену плана для одного и того же SQL. Запрос к V$SQLAREA даёт накопленные значения для того, что ещё находится в кэше.
Когда использовать
Для вопросов "что нагружало систему прошлой ночью между 02:00 и 04:00?", для выявления смены планов (тот же sql_id, другой plan_hash_value) и для составления списка кандидатов на настройку.
Внимание
Запросы к DBA_HIST_* требуют лицензии Diagnostics Pack; к V$SQLAREA — нет. AWR хранит только топ SQL (по умолчанию top-N), поэтому небольшие, но очень частые операторы могут отсутствовать. Значения V$SQLAREA теряются при вытеснении курсора из кэша. Дельты остаются корректными после перезапуска, но запрос по кэшу начинает с нуля.
Связанные материалы
- Сделать снимок AWR и сформировать отчёт AWR между двумя снимками
- Отчёт AWR diff (compare period) между двумя периодами
- Топ wait events и топ SQL из ASH за последние минуты
- Выполнить анализ ADDM и получить отчёт
- Получить отчёт SQL Monitor (выполняющийся или завершённый долгий SQL)
- Включить/выключить трассировку 10046 для сессии и обобщить её через TKPROF