Verificando consultas perniciosas
Diversas vezes, em todos os lugares por onde ando, me deparo com consultas que são extremamente perniciosas ao sistema. Aquelas consultas que demoram demais, consomem muita CPU, memória ou acesso a disco.
Às vezes a consulta em si é rápida, mas é executada inúmeras vezes e, no conjunto da obra, acaba sendo um problema para a aplicação, já peguei situações em que uma aplicação fazia consulta ao sysdate do banco para mostrar o relógio na tela, quando seria muito mais simples, e menos penoso, usar uma funcionalidade da própria aplicação sem ter que ficar consultando a cada segundo o banco de dados…
Esta consulta poderá mostrar, primeiramente as queries que trazem consultas full table scan, mas a partir dela você conseguirá obter muitas outras informações interessante como I/O, uso de memória, cardinalidade, custo, número de vezes que é executada entre outras coisas… A sua imaginação é o limite…
Select s.address, s.last_load_time, s.first_load_time, TO_CHAR ((s.cpu_time / s.executions) / 1000, '999,999,999.9999') tempo_cpu, TO_CHAR ((s.elapsed_time / s.executions) / 1000, '999,999,999.9999') tempo_decorrido, s.executions, p.object_owner, p.object_name, p.cost, p.cardinality, p.bytes, p.io_cost, p.filter_predicates, w.active_time, w.estimated_optimal_size, w.last_memory_used, w.total_executions, w.active_time
From v$sql_plan p, v$sql s, v$sql_workarea w
Where p.address = s.address
And p.address = w.address (+)
And p.hash_value = w.hash_value (+)
And p.id = w.operation_id (+)
And p.options = 'FULL'
And p.object_owner not like '%SYS%'
And SUBSTR (last_load_time, 1, 10) = TO_CHAR (sysdate, 'yyyy-mm-dd')
-- And (p.cardinality > 100
-- or p.cost > 50)
And p.filter_predicates is not null
And s.executions > 1
And (s.elapsed_time / 1000) > 1
Order by tempo_decorrido desc --(cost + cardinality) desc
Uma ferramenta que vai te auxiliar a pegar a consulta completa é a seguinte…
Select sql_text from v$sqltext where address = 'pego da consulta anterior' order by piece;
Já que abri a caixinha de ferramentas :
select p.hash_value, operation, options, object_name name, TRUNC (bytes / 1048576) "input(MB)", TRUNC (last_memory_used / 1024) last_mem, TRUNC (estimated_optimal_size/1024) opt_mem, TRUNC (estimated_onepass_size/1024) onepass_mem, DECODE (optimal_executions, null, '-', optimal_executions||'/'||onepass_executions||'/'||multipasses_executions) "O/1/M"
from v$sql_plan p, v$sql_workarea w
where p.address = w.address (+)
And p.hash_value = w.hash_value (+)
And p.id = w.operation_id (+)
And p.address = 'também da primeira consulta';
Acho que isso vai ajudar alguns 😀