SQL PLAN & SQL PLAN FIX

SQL> explain plan for
2 select * from hr.employees;

Explained.

SQL> select * from table (dbms_xplan.display);

PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 1445457117

——————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
——————————————————————————-
| 0 | SELECT STATEMENT | | 107 | 7704 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMPLOYEES | 107 | 7704 | 3 (0)| 00:00:01 |
——————————————————————————-

8 rows selected.

veya

SQL> set autotrace traceonly explain
SQL> select * from hr.employees;

Execution Plan
———————————————————-
Plan hash value: 1445457117

——————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
——————————————————————————-
| 0 | SELECT STATEMENT | | 107 | 7704 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMPLOYEES | 107 | 7704 | 3 (0)| 00:00:01 |
——————————————————————————-

ile sql plan sqlplus üzerinden alınabilir burada sadece sqlplus üzerinden sqlplan nasıl alınır onu söylemiş olduk, sql plan nasıl yorumlanır dersek, sql tuning konusunda bunu göreceğiz.

sql_id sinden sql plan çıkarma

dbms_xplan.display_cursor(sql_id=>’gnjmz1udfd9cg’) ifadesini  kullan ır isek şu an optimizer ın bu sql için seçeceği sql planı görürüz

SQL> select * from table (dbms_xplan.display_cursor(sql_id=>'gnjmz1udfd9cg'));
SQL_ID  gnjmz1udfd9cg, child number 0
-------------------------------------
UPDATE TBL_ALARM_STATUS SET END_DATE = :B2 WHERE INVERTER_ID = :B1 AND
ERROR_NUMBER='0007' AND END_DATE IS NULL

Plan hash value: 1014706028

---------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT                     |                  |       |       |   104 (100)|          |
|   1 |  UPDATE                              | TBL_ALARM_STATUS |       |       |            |          |
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| TBL_ALARM_STATUS |     1 |    21 |   104   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN                  | TBL_ALRM_STATS   |   284 |       |     4   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("INVERTER_ID"=:B1)
   3 - access("ERROR_NUMBER"=U'0007' AND "END_DATE" IS NULL)


22 rows selected.

dbms_xplan_cursor_awr ile aynı komutu çalıştırdığımızda en son awr snapshot içerisndeki sql planı görürüz.

SQL> select * from table (dbms_xplan.display_awr('gnjmz1udfd9cg'));
SQL_ID gnjmz1udfd9cg
--------------------
UPDATE TBL_ALARM_STATUS SET END_DATE = :B2 WHERE INVERTER_ID = :B1 AND
ERROR_NUMBER='0007' AND END_DATE IS NULL

Plan hash value: 2256970134

---------------------------------------------------------------------------------------
| Id  | Operation          | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |                  |       |       |  2781 (100)|          |
|   1 |  UPDATE            | TBL_ALARM_STATUS |       |       |            |          |
|   2 |   TABLE ACCESS FULL| TBL_ALARM_STATUS |     1 |    21 |  2781   (1)| 00:00:01 |
---------------------------------------------------------------------------------------


15 rows selected.

Burada iki faklı sql plan var bakalım gerçekten v$active_session_history ve dba_hist_active_sess_history view larında bu sql_id için farklı planlar var mı?

SQL> SELECT distinct SQL_PLAN_HASH_VALUE FROM DBA_HIST_ACTIVE_SESS_HISTORY WHERE SQL_ID='gnjmz1udfd9cg';
         1014706028
         2256970134
                  0


SQL> select distinct SQL_PLAN_HASH_VALUE from v$active_session_history where sql_id='gnjmz1udfd9cg';
         1014706028
         2256970134
                  0

iki adet sql planımız var peki 1. Plan 225 ile başlayan sonraki plan ise 101 ile başlayan planlardır. Biz planın değişmesini istemediğimiz halde optimizer tarafından bazen farklı bir plan devreye alınabiliyor, bu durumda sql’i eski plana fix yapmayı isteyebiliriz yapmalıyız?

SQL PLAN FIX

SQL>    select sql_plan_hash_value,sql_id from dba_hist_active_sess_history
   where sql_id='gnjmz1udfd9cg' group by sql_plan_hash_value,sql_id;  2

SQL_PLAN_HASH_VALUE SQL_ID
------------------- -------------
         1014706028 gnjmz1udfd9cg
         2256970134 gnjmz1udfd9cg
                  0 gnjmz1udfd9cg

Planı yükleyelim

declare
    lv_plan number;
begin
    lv_plan:=dbms_spm.load_plans_from_cursor_cache  
        (sql_id=>'gnjmz1udfd9cg',
        plan_hash_value => '2256970134',
        fixed =>'NO');
end;

Planı yükledikten sonra dba_sql_baselines view ından sql_handle ve plan_name bilgilerini alalım, bu bilgiler ile de istediğimiz sql planın fix işlemini gerçekleştirelim;

SQL> select sql_handle, plan_name,fixed from dba_sql_plan_baselines where origin like '%MANUAL%';

SQL_HANDLE                     PLAN_NAME                                FIX
------------------------------ ---------------------------------------- ---
SQL_4b1050e80764fe67           SQL_PLAN_4q42hx03q9zm72613255d           NO

Şimdi Planı fixleyelim

declare
 lv_plan_fx number;
begin
 lv_plan_fx:=DBMS_SPM.alter_sql_plan_baseline(
            sql_handle=>'SQL_4b1050e80764fe67',
            plan_name => 'SQL_PLAN_4q42hx03q9zm72613255d',
            attribute_name => 'fixed',
            attribute_value => 'YES');
end;

Kontrol edelim;

SQL> select sql_handle, plan_name,fixed from dba_sql_plan_baselines where origin like '%MANUAL%';

SQL_HANDLE                     PLAN_NAME                                FIX
------------------------------ ---------------------------------------- ---
SQL_4b1050e80764fe67           SQL_PLAN_4q42hx03q9zm72613255d           YES

DECLARE lv_plans_dropped PLS_INTEGER; 
BEGIN 
lv_plans_dropped := DBMS_SPM.drop_sql_plan_baseline (sql_handle => 'SQL_4b1050e80764fe67',plan_name => 'SQL_PLAN_4q42hx03q9zm72613255d'); DBMS_OUTPUT.put_line('Plans Dropped: ' || lv_plans_dropped); 
END; 
/