Oracleでパフォーマンスの低いSQLクエリを見つけるにはどうすればよいですか?
Oracleは、共有SQL領域の統計を維持し、SQL文字列(v $ sqlarea)ごとに1行を含みます。しかし、どれがパフォーマンスが悪いのかをどのように識別できますか?
この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
askTom-Oracleから得た完全な情報。あなたのお役に立てばと思います
select *
from v$sql
where buffer_gets > 1000000
or disk_reads > 100000
or executions > 50000
次のクエリは、大量のディスク読み取りを実行する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
ステートメントを実行する前。
このクエリは、古いOracle SQLチューニングブック(残念ながらもうありません)で見つけたので、おaびしますが、帰属はありません。
これを行うにはいくつかの可能な方法がありますが、tkprofのためのグーグルがあります
GUIはありません...それは完全にコマンドラインであり、Oracle初心者にとっては恐ろしいことかもしれません。しかし、それは非常に強力です。
このリンクは良いスタートのようです: