Showing posts with label set timing off. Show all posts
Showing posts with label set timing off. Show all posts

Wednesday, May 30, 2012

Alter System Flush Shared_Pool and Alter System Flush Buffer_Cache

This example shows the effect of the alter system flush shared_pool and alter system flush buffer_cache commands. It was tested on Oracle 11.2. First create a table with some rows to count:
 
SQL> create table tab1
  2  as select * from dba_tables
  3  /
 
Table created.
 
SQL> begin
  2  for a in 1..5
  3  loop
  4  insert into tab1 select * from tab1;
  5  end loop;
  6  end;
  7  /
 
PL/SQL procedure successfully completed.
 
SQL>
 
The shared pool contains the library cache. This stores the parsing details and execution plans for SQL statements which have been run. You can remove these details by flushing the shared pool:
 
SQL> alter system flush shared_pool
  2  /
 
System altered.
 
SQL>
 
The buffer cache contains blocks which have been read from disk. You can flush the buffer cache as follows:
 
SQL> alter system flush buffer_cache
  2  /
 
System altered.
 
SQL>
 
Now you can get a baseline time (1.94 seconds) for parsing the SQL, creating an execution plan, getting the database blocks from disk and counting the rows:
 
SQL> set timing on
SQL> select count(*) from tab1
  2  /
 
  COUNT(*)
----------
     97920
 
Elapsed: 00:00:01.94
SQL>
 
Count the rows again. This time the SQL is already in the library cache so it does not need to be reparsed. The database blocks are still in the buffer cache from the previous SQL statement so there is no need to get them from disk either. As a result, this statement is much quicker (0.04 seconds):
 
SQL> select count(*) from tab1
  2  /
 
  COUNT(*)
----------
     97920
 
Elapsed: 00:00:00.04
SQL> set timing off
SQL>
 
Now flush the shared pool to remove the SQL from the library cache:
 
SQL> alter system flush shared_pool
  2  /
 
System altered.
 
SQL>
 
Run the SQL again. Having to reparse the SQL and recreate the execution plan adds a fraction of a second to the elapsed time:
 
SQL> set timing on
SQL> select count(*) from tab1
  2  /
 
  COUNT(*)
----------
     97920
 
Elapsed: 00:00:00.07
SQL> set timing off
SQL>
 
Flush the buffer cache to remove the database blocks:
 
SQL> alter system flush buffer_cache
  2  /
 
System altered.
 
SQL>
 
Count the rows in the table as before. Having to fetch the database blocks from disk again adds over a second to the elapsed time:
 
SQL> set timing on
SQL> select count(*) from tab1
  2  /
 
  COUNT(*)
----------
     97920
 
Elapsed: 00:00:01.49
SQL> set timing off
SQL>
 
Finally, flush both the shared pool AND the buffer cache:
 
SQL> alter system flush shared_pool
  2  /
 
System altered.
 
SQL> alter system flush buffer_cache
  2  /
 
System altered.
 
SQL>
 
Count the rows in the table for the last time. This involves reparsing the SQL, recreating the execution plan and fetching the database blocks. This time the elapsed time is roughly the same as the baseline time at the start:
 
SQL> set timing on
SQL> select count(*) from tab1
  2  /
 
  COUNT(*)
----------
     97920
 
Elapsed: 00:00:01.85
SQL> set timing off
SQL>

Friday, May 18, 2012

V$MYSTAT

Tested on Oracle 11.2. This view stores information for the current session:
 
SQL> desc v$mystat
Name                       Null?    Type
-------------------------- -------- ------------------
SID                                 NUMBER
STATISTIC#                          NUMBER
VALUE                               NUMBER
 
SQL>
 
Although there is a column called SID in the view, it only has 1 value, the SID for the current session:
 
SQL> select distinct sid from v$mystat
  2  /
 
       SID
----------
       394
 
SQL>
 
If you join it with v$statname, you can pick out individual statistics like this:
 
SQL> select value/100 CPU_used
  2  from v$mystat a, v$statname b
  3  where a.statistic# = b.statistic#
  4  and name = 'CPU used by this session'
  5  /
 
  CPU_USED
----------
       .03
 
SQL>
 
An ideal way to use lots of CPU time is to have a join without a join condition:
 
SQL> set timing on
SQL> select count(*)
  2  from dba_tables a, dba_tables b
  3  /
 
  COUNT(*)
----------
   9375844
 
Elapsed: 00:03:29.23
SQL> set timing off
 
Now that the SQL has finished, you can see that the elapsed time was 209 seconds and the CPU time used was 144 seconds:
 
SQL> select value/100 CPU_used
  2  from v$mystat a, v$statname b
  3  where a.statistic# = b.statistic#
  4  and name = 'CPU used by this session'
  5  /
 
  CPU_USED
----------
    144.23
 
SQL>

Thursday, December 29, 2011

Automatic Parallel Execution

In 11g release 2, Oracle introduced the following new parameters:
 
parallel_degree_policy
parallel_min_time_threshold
 
The default setting of parallel_degree_policy is manual. With this value, the automatic parallel execution of SQL statements is disabled. This is how Oracle worked before 11g release 2.
 
Setting this parameter to auto enables this functionality. Oracle then parses an SQL statement, works out its execution plan and estimates how long it will take. If this value is greater than  parallel_min_time_threshold seconds, the statement runs in parallel. You can see what difference this makes in the example below, which runs the same query twice.
 
Automatic parallel execution is turned off for the first run:
 
SQL> select value from v$parameter
  2  where name = 'parallel_min_time_threshold'
  3  /
 
VALUE
--------------------
AUTO
 
SQL> select value from v$parameter
  2  where name = 'parallel_degree_policy'
  3  /
 
VALUE
--------------------
MANUAL
 
SQL> set timing on
SQL> select count(*) from
  2  (select a.table_name from
  3   dba_tables a, dba_tables b)
 4  /
 
  COUNT(*)
----------
   9247681
 
Elapsed: 00:02:00.41
SQL> set timing off
 
And the query takes just over 2 minutes. Automatic parallel execution is then turned on for the second run:
 
SQL> alter session set
  2  parallel_min_time_threshold = 1
  3  /
 
Session altered.
 
SQL> alter session set
  2  parallel_degree_policy = 'AUTO'
  3  /
 
Session altered.
 
SQL> set timing on
SQL> select count(*) from
  2  (select a.table_name from
  3   dba_tables a, dba_tables b)
  4  /
 
  COUNT(*)
----------
   9247681
 
Elapsed: 00:00:37.15
SQL> set timing off
 
And the query takes less than 40 seconds.