Oracle Scratchpad

April 10, 2007

SQL Costs

Filed under: Performance, Troubleshooting — Jonathan Lewis @ 8:31 pm UTC Apr 10,2007

Here’s a quick and dirty bit of SQL I use from time to time to check whats going on with a “popular” piece of SQL, i.e. a piece of code that is run very frequently. All it does is compare a few of the statistics from v$sql with their previous values from the last time the script was run. 

As you can see, the script is the 10g version, using the sql_id to access a single statement in the library cache with maximum efficiency – change this to the hash_value for earlier versions of Oracle.

All I do with this script is identify a single ‘interesting’ statement – possibly by checking a recent statspack report for the the most frequently executed statements – and slot in the appropriate sql_id and child_number. Of course, some statements will have multiple child cursors, so a precursor to setting up this script is to pick an interesting child.

As you can see, I use the SQL*Plus new_value feature to capture the most recent values reported for the statistics I am interested in – but use the previous captured values to generate the ‘deltas’. (And to get things going, I define the inputs as zero for the first run of the script).

So all you do is pick your statement, adjust the script, then run it every few seconds for a couple of minutes.

Occasionally it nice to have something like this to sample v$sql in near-real time rather than relying on the longer-term averages you get from statspack as an indicator of the work done and results acquired by a single statement.


set linesize 144
set verify off  

column	executions	new_value m_exe_ct
column	rows_processed	new_value m_row_ct
column	buffer_gets	new_value m_buf_ct
column	disk_reads	new_value m_dsk_ct  

define m_exe_ct = 0
define m_row_ct = 0
define m_buf_ct = 0
define m_dsk_ct = 0  

select
	sql_id,
	child_number,
	executions,
	executions - &m_exe_ct 			exe_delta,
	buffer_gets,
	buffer_gets - &m_buf_ct 		buf_delta,
	disk_reads,
	disk_reads - &m_dsk_ct 			dsk_delta,
	rows_processed,
	rows_processed - &m_row_ct 		row_delta,
	round(
		(rows_processed - &m_row_ct) /
		nullif(executions - &m_exe_ct,0)
	)					rows_per_exe,
	round(
		(buffer_gets - &m_buf_ct) /
		nullif(executions - &m_exe_ct,0)
	)					bufs_per_exe,
	round(
		(disk_reads - &m_dsk_ct) /
		nullif(executions - &m_exe_ct,0)
	)					dsks_per_exe
from
	v$sql
where
	sql_id = '6vba5y39vcq1f'
and	child_number = 0
;  

Obviously, you can follow the pattern of the code to pick your own metrics – I tend to find “work done per row” and “work done per execution” quite helpful; you may want to review work done in terms of CPU time, sorts, and any other basic metrics available in the view – unfortunately you have to be a little selective otherwise the output is to wide.

I’ve attached a sample of the output from running the above example a few times – but I’ve manually adjusted the output, eliminating columns, to allow it to fit on the page:


SQL> /  

EXECUTIONS EXE_DELTA  BUFFER_GETS  BUF_DELTA ROWS_PROCESSED ROW_DELTA  ROWS_PER_EXE BUFS_PER_EXE
---------- ---------- ----------- ---------- -------------- ---------- ------------ ------------
   1663712         19   892482440       7355      114727466        469           25          387  

SQL> /  

EXECUTIONS EXE_DELTA  BUFFER_GETS  BUF_DELTA ROWS_PROCESSED  ROW_DELTA ROWS_PER_EXE BUFS_PER_EXE
---------- ---------- ----------- ---------- -------------- ---------- ------------ ------------
   1663728         16   892488545       6105      114727910        444           28          382   

SQL> /  

EXECUTIONS EXE_DELTA  BUFFER_GETS  BUF_DELTA ROWS_PROCESSED  ROW_DELTA ROWS_PER_EXE BUFS_PER_EXE
---------- ---------- ----------- ---------- -------------- ---------- ------------ ------------
   1663744         16   892496194       7649      114728240        330           21          478   

In this case, the sampling showed that the costs and result sets were fairly stable – the interesting cases tend to be the ones which show a very wide variation in costs or results.

1 Comment »

  1. You might also expand it to check whether something has changed recently – comparing resource/executions against your resource_delta/executions_delta.

    Comment by Alberto Dell'Era — April 11, 2007 @ 9:48 pm UTC Apr 11,2007 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.