Comment puis-je trouver des requêtes SQL peu performantes dans Oracle?
Oracle maintient des statistiques sur la zone SQL partagée et contient une ligne par chaîne SQL (v $ sqlarea). Mais comment identifier lequel d'entre eux est mal performant?
J'ai trouvé que cette instruction SQL était un endroit utile pour commencer (désolé, je ne peux pas attribuer cela à l'auteur d'origine; je l'ai trouvé quelque part sur Internet):
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
/
Cela trouve les principales instructions SQL qui sont actuellement stockées dans le cache SQL triées par temps écoulé. Les instructions disparaîtront du cache au fil du temps, il peut donc être inutile d'essayer de diagnostiquer le travail par lots de la nuit dernière lorsque vous vous mettez au travail à midi.
Vous pouvez également essayer de classer par disk_reads et exécutions. Les exécutions sont utiles car certaines applications pauvres envoient trop souvent la même instruction SQL. Ce SQL suppose que vous utilisez correctement les variables de liaison.
Ensuite, vous pouvez prendre le sql_id
et child_number
d'une déclaration et les nourrir dans ce bébé: -
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', &child));
Cela montre le plan réel du cache SQL et le texte intégral du SQL.
Vous pouvez trouver des analyses de table complètes gourmandes en disque avec quelque chose comme ceci:
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;
Vous pouvez prendre le tampon moyen obtenu par exécution pendant une période d'activité de l'instance:
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
l'information complète que j'ai obtenue de askTom-Oracle. J'espère que ça t'aide
select *
from v$sql
where buffer_gets > 1000000
or disk_reads > 100000
or executions > 50000
La requête suivante renvoie des instructions SQL qui effectuent un grand nombre de lectures de disque (inclut également l'utilisateur incriminé et le nombre d'exécutions de la requête):
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
Exécutez la requête en tant que SYS et ajustez le nombre de lectures de disque en fonction de ce que vous jugez excessif (100 000 fonctionne pour moi).
J'ai utilisé cette requête très récemment pour retrouver les utilisateurs qui refusent de profiter de Explain Plans
avant d'exécuter leurs instructions.
J'ai trouvé cette requête dans un vieux livre de réglage Oracle SQL (que je n'ai malheureusement plus), donc excuses, mais pas d'attribution.
Il existe plusieurs façons de procéder, mais utilisez un google pour tkprof
Il n'y a pas d'interface graphique ... c'est entièrement en ligne de commande et peut-être une touche intimidante pour les débutants Oracle; mais c'est très puissant.
Ce lien ressemble à un bon début: