2008-11-25 72 views
29

¿Cómo puedo encontrar consultas SQL de bajo rendimiento en Oracle?Top 5 consultas SQL que consumen tiempo en Oracle

Oracle mantiene estadísticas sobre el área SQL compartida y contiene una fila por cadena SQL (v $ sqlarea). Pero, ¿cómo podemos identificar cuál de ellos está funcionando mal?

Respuesta

1

Hay una serie de posibles maneras de hacer esto, pero tienen un google para TKPROF

No hay ninguna interfaz gráfica de usuario ... es por completo la línea de comandos y, posiblemente, un toque intimidante para los principiantes de Oracle; pero es muy poderoso.

Este enlace se parece a un buen comienzo:

http://www.oracleutilities.com/OSUtil/tkprof.html

+0

¿Hay alguna manera de obtener los datos con una consulta sql? ¿Oracle mantiene datos relevantes en algunas tablas del sistema? –

+0

No mantiene tantos datos en las tablas del sistema como se obtiene con tkprof. Vea mi respuesta de una manera rápida y sucia para buscar malas declaraciones. tkprof es mejor, pero debe configurar específicamente una prueba y ejecutarla. –

42

encontré esta instrucción SQL para ser un lugar útil para empezar (lo siento, no puedo atribuir esto al autor original; lo encontré en alguna parte en el 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 
/

Esto encuentra las sentencias SQL superiores que están almacenados actualmente en la memoria caché de SQL ordenada por el tiempo transcurrido. Las declaraciones desaparecerán de la memoria caché con el tiempo, por lo que no sería bueno intentar diagnosticar el trabajo por lotes de la noche anterior cuando ingresa al trabajo al mediodía.

También puede intentar ordenar por disk_reads y ejecuciones. Las ejecuciones son útiles porque algunas aplicaciones deficientes envían la misma instrucción SQL demasiadas veces. Este SQL supone que usa variables de vinculación correctamente.

A continuación, se puede tomar el sql_id y child_number de una declaración y alimentarlos en este bebé: -

SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', &child)); 

Esto muestra el plan actual de la caché de SQL y el texto completo del SQL.

+0

Debe agregar elapsed_time en la selección, de lo contrario, es bastante confuso. –

-1

Si bien la búsqueda me dio la siguiente consulta, que hace el trabajo con un supuesto (de ejecución de consultas de tiempo> 6 segundos)


nombre de usuario SELECT, sql_text, sofar, totalwork, unidades

de v $ sql, v $ session_longops

DONDE sql_address = dirección Y = sql_hash_value hash_value

ORDER BY dirección, hash_value, CHILD_NUMBER ;


Creo que la consulta anterior enumerará los detalles para el usuario actual.

¡Los comentarios son bienvenidos!

+0

Esta consulta no está limitada al usuario actual, y solo funcionaría si la consulta aparece en v $ session_longops. Longops registra qué tan lejos a través de una clasificación, escaneo de tabla, índice de escaneo completo está Oracle. Si su consulta es lenta debido a un mal plan de bucles anidados, no se mostrará porque no hay longops. –

1

Depende de qué versión de Oracle tengas, para 9i y debajo de Statspack es lo que buscas, 10g y superior, quieres awr, estas herramientas te darán los mejores sql y muchas otras cosas.

4

Usted podría tomar el buffer promedio recibe por cada ejecución durante un periodo de actividad de la instancia:

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 
15

Usted puede encontrar uso intensivo del disco recorridos de tabla completa con algo como esto:

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; 
+0

¿No es DISK_READS el número total de lecturas de disco, por lo que no necesita multiplicar por ejecuciones? –

1

El La consulta siguiente devuelve instrucciones SQL que realizan un gran número de lecturas de disco (también incluye al usuario infractor y la cantidad de veces que se ha ejecutado la consulta):

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 

Ejecute la consulta como SYS y ajuste el número de lecturas de disco según lo que considere excesivo (100.000 trabajos para mí).

He utilizado esta consulta muy recientemente para localizar a los usuarios que se niegan a aprovechar Explain Plans antes de ejecutar sus declaraciones.

Encontré esta consulta en un libro de ajuste de Oracle SQL antiguo (que desafortunadamente ya no tengo), así que disculpas, pero no atribución.

1

la información completa que obtuve de askTom-Oracle. Espero que lo ayude

select * 
from v$sql 
where buffer_gets > 1000000 
or disk_reads > 100000 
or executions > 50000