Как найти неудачные SQL-запросы в Oracle?Топ 5 трудоемких SQL-запросов в Oracle
Oracle поддерживает статистику по общей области SQL и содержит одну строку на строку SQL (v $ sqlarea). Но как мы можем определить, какой из них плохо работает?
Как найти неудачные SQL-запросы в Oracle?Топ 5 трудоемких SQL-запросов в Oracle
Oracle поддерживает статистику по общей области SQL и содержит одну строку на строку SQL (v $ sqlarea). Но как мы можем определить, какой из них плохо работает?
Есть несколько возможных способов сделать это, но есть Google для TKPROF
Там нет GUI ... это полностью командной строки и, возможно, сенсорный пугающим для начинающих Oracle; но он очень мощный.
Эта ссылка выглядит как хороший старт:
Я нашел этот 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.
Вы должны добавить elapsed_time в select, иначе это довольно запутанно. – 2014-11-05 11:37:02
При поиске я получил следующий запрос, который делает работу с одним условием (выполнения запросов> 6 секунд)
SELECT, имя пользователя, sql_text, ГНФАР, totalwork, блоки
ОТ V $ SQL, v $ SESSION_LONGOPS
ГДЕ sql_address = адрес и sql_hash_value = hash_value
ORDER BY адрес, hash_value, child_number ;
Я думаю, что над запросом будут перечислены детали для текущего пользователя.
Комментарии приветствуются!
Этот запрос не ограничивается текущим пользователем и будет работать только в том случае, если запрос появляется в v $ session_longops. Longops записывает, как далеко через сортировку, сканирование таблицы, полное сканирование индекса Oracle. Если ваш запрос медленный из-за плохого плана вложенных циклов, он не будет отображаться, потому что нет локопов. – 2008-11-26 01:51:16
Вы могли бы взять средний буфер получает за выполнение в период деятельности, например:
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
Вы можете найти на диск интенсивного полного сканирования таблицы с чем-то вроде этого:
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;
следующий запрос возвращает 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 Server Oracle (чего, к сожалению, у меня нет), поэтому извиняюсь, но не атрибуции.
полная информация, полученная от askTom-Oracle. Надеюсь, это вам поможет
select *
from v$sql
where buffer_gets > 1000000
or disk_reads > 100000
or executions > 50000
Есть ли способ получить данные с помощью sql-запроса? Поддерживает ли Oracle соответствующие данные в некоторых системных таблицах? – 2008-11-25 10:06:00
Он не поддерживает столько данных в системных таблицах, сколько вы получаете с tkprof. См. Мой ответ для быстрого и грязного способа поиска плохих высказываний. tkprof лучше, но вам нужно специально настроить тест и запустить его. – 2008-11-26 01:49:08