Wednesday 1 April 2015

Using the Execution Plan in Oracle

 Performance tuning or query tuning may be a heavy weight term but practicing it is much more interesting and by practicing we find that query tuning is not Rocket Science
In this demo we shall explore the execution plan of a query and find out the bottlenecks in poor performing queries.
Let us take a sample query:-
select e.employee_id, d.department_name, e.first_name, e.last_name, e.hire_date, l.city
from demo_emp e, demo_dept d, demo_location l
where d.department_id = 60 and d.department_id = e.department_id and l.location_id = d.location_id;

To get the execution plan we need to follow the mentioned steps:-
GENERATING THE EXECUTION PLAN
________________________________

Step 1 - explain plan for
                select e.employee_id, d.department_name, e.first_name, e.last_name, e.hire_date, l.city
                from demo_emp e, demo_dept d, demo_location l
                where d.department_id = 60 and d.department_id = e.department_id and l.location_id = d.location_id;


OUTPUT:-
explain plan succeeded.




Step 2 - select * from table(dbms_xplan.display);

OUTPUT:-

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                            
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3010691218                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                             
-------------------------------------------------------------------------------------                                                                                                                                                                                                                        
| Id  | Operation           | Name          | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                                        
-------------------------------------------------------------------------------------                                                                                                                                                                                                                        
|   0 | SELECT STATEMENT    |               |     5 |   670 |    10  (10)| 00:00:01 |                                                                                                                                                                                                                        
|*  1 |  HASH JOIN          |               |     5 |   670 |    10  (10)| 00:00:01 |                                                                                                                                                                                                                       
|*  2 |   HASH JOIN         |               |     1 |    73 |     7  (15)| 00:00:01 |                                                                                                                                                                                                                        
|*  3 |    TABLE ACCESS FULL| DEMO_DEPT     |     1 |    43 |     3   (0)| 00:00:01 |                                                                                                                                                                                                                        
|   4 |    TABLE ACCESS FULL| DEMO_LOCATION |    23 |   690 |     3   (0)| 00:00:01 |                                                                                                                                                                                                                        
|*  5 |   TABLE ACCESS FULL | DEMO_EMP      |     5 |   305 |     3   (0)| 00:00:01 |                                                                                                                                                                                                                        
-------------------------------------------------------------------------------------                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                             
Predicate Information (identified by operation id):                                                                                                                                                                                                                                                          
---------------------------------------------------                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                             
   1 - access("D"."DEPARTMENT_ID"="E"."DEPARTMENT_ID")                                                                                                                                                                                                                                                       
   2 - access("L"."LOCATION_ID"="D"."LOCATION_ID")                                                                                                                                                                                                                                                           
   3 - filter("D"."DEPARTMENT_ID"=60)                                                                                                                                                                                                                                                                        
   5 - filter("E"."DEPARTMENT_ID"=60)                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                             
Note                                                                                                                                                                                                                                                                                                         
-----                                                                                                                                                                                                                                                                                                        
   - dynamic sampling used for this statement (level=2)                                                                                                                                                                                                                                                      

24 rows selected
****************************************************************************



Now Let us do a detailed analysis.
There are multiple things the execution plan says:-
1 –  Total cost is 36 (just add all the costs)
Cost (%CPU)
    10  (10)
    10  (10)
     7  (15)
     3   (0)
     3   (0)
     3   (0)


2 – Total memory used is 2451 Bytes
Bytes
670
670
73
43
690
305

3 – There are 3 Full table scans
    TABLE ACCESS FULL
 DEMO_DEPT     
1
43
    TABLE ACCESS FULL
 DEMO_LOCATION
23
690
   TABLE ACCESS FULL
 DEMO_EMP     
5
305

This is the major pain point in which we shall focus in our demo. We shall try to reduce the number of full table scans.
The most common approach is to use an index.
“Our demo developer might have ignored the fact and is complaining about slow performing query”

Let us create an index in first table executed “DEMO_DEPT”
CREATE INDEX DEMO_DEPT_ID ON DEMO_DEPT (DEPARTMENT_NAME);

Now if we explain again we find the plan as

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                            
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2307362991                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                             
-----------------------------------------------------------------------------------------------                                                                                                                                                                                                              
| Id  | Operation                     | Name          | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                              
-----------------------------------------------------------------------------------------------                                                                                                                                                                                                              
|   0 | SELECT STATEMENT              |               |     5 |   670 |     9  (12)| 00:00:01 |                                                                                                                                                                                                             
|*  1 |  HASH JOIN                    |               |     5 |   670 |     9  (12)| 00:00:01 |                                                                                                                                                                                                              
|*  2 |   HASH JOIN                   |               |     1 |    73 |     6  (17)| 00:00:01 |                                                                                                                                                                                                              
|   3 |    TABLE ACCESS BY INDEX ROWID| DEMO_DEPT     |     1 |    43 |     2   (0)| 00:00:01 |                                                                                                                                                                                                              
|*  4 |     INDEX RANGE SCAN          | DEMO_DPT_ID   |     1 |       |     1   (0)| 00:00:01 |                                                                                                                                                                                                              
|   5 |    TABLE ACCESS FULL          | DEMO_LOCATION |    23 |   690 |     3   (0)| 00:00:01 |                                                                                                                                                                                                              
|*  6 |   TABLE ACCESS FULL           | DEMO_EMP      |     5 |   305 |     3   (0)| 00:00:01 |                                                                                                                                                                                                             
-----------------------------------------------------------------------------------------------      

Now we avoided one full table scan and used an INDEX RANGE SCAN. The cost reduces to 33. Thus now the query shall execute faster.
This number may not be very impressive for this demo tables which are very small in size. But in real life a lot can be gained by Indexing. Try the same for the other tables and see the difference.
 In this demo we covered the index part only, stay tuned for more…


Disclaimer – This document is intended for information purpose only. Please communicate with me on – akash007.pramanik@gmail.com before using in any live production environment.











1 comment: