Как я могу найти неудачные SQL-запросы в Oracle?
Oracle поддерживает статистику по общей области SQL и содержит одну строку на строку SQL (v $sqlarea). Но как мы можем определить, какой из них плохо работает?
Как я могу найти неудачные SQL-запросы в Oracle?
Oracle поддерживает статистику по общей области SQL и содержит одну строку на строку SQL (v $sqlarea). Но как мы можем определить, какой из них плохо работает?
Я нашел этот оператор SQL полезным местом для начала (извините, я не могу отнести это к оригинальному автору, я нашел его где-то в Интернете):
SELECT * FROM
(SELECT
sql_fulltext,
sql_id,
elapsed_time,
child_number,
disk_reads,
executions,
first_load_time,
last_load_time
FROM v$sql
ORDER BY elapsed_time DESC)
WHERE ROWNUM < 10
/
Это находит верхние операторы SQL, которые в настоящее время хранятся в кеше SQL, упорядоченном по истекшему времени. С течением времени из кэша исчезнут высказывания, поэтому было бы неплохо попытаться диагностировать последнее пакетное задание, когда вы входите в работу в полдень.
Вы также можете попробовать упорядочить с помощью disk_reads и исполнений. Исполнения полезны, потому что некоторые бедные приложения слишком много раз отправляют один и тот же SQL-оператор. Этот SQL предполагает, что вы правильно используете привязывающие переменные.
Затем вы можете взять sql_id
и child_number
оператора и передать их этому ребенку: -
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', &child));
Это показывает фактический план из кеша SQL и полного текста SQL.
Вы можете найти полное сканирование таблиц на жестком диске с помощью чего-то вроде этого:
SELECT Disk_Reads DiskReads, Executions, SQL_ID, SQL_Text SQLText,
SQL_FullText SQLFullText
FROM
(
SELECT Disk_Reads, Executions, SQL_ID, LTRIM(SQL_Text) SQL_Text,
SQL_FullText, Operation, Options,
Row_Number() OVER
(Partition By sql_text ORDER BY Disk_Reads * Executions DESC)
KeepHighSQL
FROM
(
SELECT Avg(Disk_Reads) OVER (Partition By sql_text) Disk_Reads,
Max(Executions) OVER (Partition By sql_text) Executions,
t.SQL_ID, sql_text, sql_fulltext, p.operation,p.options
FROM v$sql t, v$sql_plan p
WHERE t.hash_value=p.hash_value AND p.operation='TABLE ACCESS'
AND p.options='FULL' AND p.object_owner NOT IN ('SYS','SYSTEM')
AND t.Executions > 1
)
ORDER BY DISK_READS * EXECUTIONS DESC
)
WHERE KeepHighSQL = 1
AND rownum <=5;
Вы можете получить средний буфер для каждого выполнения в течение периода действия экземпляра:
SELECT username,
buffer_gets,
disk_reads,
executions,
buffer_get_per_exec,
parse_calls,
sorts,
rows_processed,
hit_ratio,
module,
sql_text
-- elapsed_time, cpu_time, user_io_wait_time, ,
FROM (SELECT sql_text,
b.username,
a.disk_reads,
a.buffer_gets,
trunc(a.buffer_gets / a.executions) buffer_get_per_exec,
a.parse_calls,
a.sorts,
a.executions,
a.rows_processed,
100 - ROUND (100 * a.disk_reads / a.buffer_gets, 2) hit_ratio,
module
-- cpu_time, elapsed_time, user_io_wait_time
FROM v$sqlarea a, dba_users b
WHERE a.parsing_user_id = b.user_id
AND b.username NOT IN ('SYS', 'SYSTEM', 'RMAN','SYSMAN')
AND a.buffer_gets > 10000
ORDER BY buffer_get_per_exec DESC)
WHERE ROWNUM <= 20
Существует несколько возможных способов сделать это, но у вас есть google для tkprof
Нет графического интерфейса... это полностью командная строка и, возможно, пугающее для новичков Oracle; но он очень мощный.
Эта ссылка выглядит как хороший старт:
Это зависит от того, какая версия оракула у вас есть, для 9i и ниже Statspack - это то, что вам нужно, 10g и выше, вы хотите awr, оба этих инструмента предоставят вам верхний sql и много других вещей.
Следующий запрос возвращает SQL-операторы, которые выполняют большое количество чтения на диске (также включает пользователя-нарушителя и количество запросов, которые были выполнены):
SELECT t2.username, t1.disk_reads, t1.executions,
t1.disk_reads / DECODE(t1.executions, 0, 1, t1.executions) as exec_ratio,
t1.command_type, t1.sql_text
FROM v$sqlarea t1, dba_users t2
WHERE t1.parsing_user_id = t2.user_id
AND t1.disk_reads > 100000
ORDER BY t1.disk_reads DESC
Запустите запрос как SYS и отрегулируйте количество считываний дисков в зависимости от того, что вы считаете чрезмерным (100 000 работает для меня).
Я использовал этот запрос совсем недавно, чтобы отследить пользователей, которые отказываются использовать Explain Plans
перед выполнением своих инструкций.
Я нашел этот запрос в старой книге настройки SQL Oracle (чего, к сожалению, я больше не имею), поэтому извиняюсь, но не атрибуции.
полную информацию, полученную от askTom-Oracle. Надеюсь, это поможет вам.
select *
from v$sql
where buffer_gets > 1000000
or disk_reads > 100000
or executions > 50000
При поиске я получил следующий запрос, который выполняет задание с одним допущением (время выполнения запросa > 6 секунд)
SELECT имя пользователя, sql_text, sofar, totalwork, units
FROM v $sql, v $session_longops
WHERE sql_address = адрес И sql_hash_value = hash_value
ORDER BY address, hash_value, child_number;
Я думаю, что над запросом будут перечислены данные для текущего пользователя.
Комментарии приветствуются!