天天看點

sql_profile的使用(一)

今天看了老熊關于sql_profile的講解,受益匪淺,自己在本機也做了一通,感覺好記性不如爛筆頭還是得多總結總測試才能真正了解。

準備的資料如下,建立兩個表,一個大,一個小,然後做表分析

SQL> create table t1 as select object_id,object_name from dba_objects where rownum

Table created.

SQL> create table t2 as select * from dba_objects;  

SQL> create index t2_idx on t2(object_id);

Index created.

SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,method_opt=>'for all columns size 1');

PL/SQL procedure successfully completed.

SQL>  exec dbms_stats.gather_table_stats(user,'t2',cascade=>true,method_opt=>'for all columns size 1');

不加任何hint,檢視執行計劃,可以看到兩個表都走了全表掃描。

SQL> set autot trace exp stat

SQL> set linesize 200

SQL> set pages 100

SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 

26 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 1838229974

-----------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost  |

|   0 | SELECT STATEMENT   |      |  2500 |   112K|   122 |

|*  1 |  HASH JOIN         |      |  2500 |   112K|   122 |

|*  2 |   TABLE ACCESS FULL| T1   |  2500 | 77500 |     8 |

|   3 |   TABLE ACCESS FULL| T2   |   269K|  3952K|   107 |

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")

   2 - filter("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS

              NOT NULL)

Note

-----

   - cpu costing is off (consider enabling it)

Statistics

          1  recursive calls

          0  db block gets

       4477  consistent gets

          0  physical reads

          0  redo size

       1669  bytes sent via SQL*Net to client

        531  bytes received via SQL*Net from client

          3  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

         26  rows processed

如果手動調優,加入Hint,可以參考如下的形式,可以看到性能有了成倍的提升。

SQL> select /*+ use_nl(t1 t2) index(t2) */ t1.*,t2.owner   

  2           from t1,t2   

  3           where t1.object_name like '%T1%'   

     and t1.object_id=t2.object_id;  4  

Plan hash value: 1022743391

-----------------------------------------------------------------------

| Id  | Operation                    | Name   | Rows  | Bytes | Cost  |

|   0 | SELECT STATEMENT             |        |  2500 |   112K|   258 |

|   1 |  NESTED LOOPS                |        |       |       |       |

|   2 |   NESTED LOOPS               |        |  2500 |   112K|   258 |

|*  3 |    TABLE ACCESS FULL         | T1     |  2500 | 77500 |     8 |

|*  4 |    INDEX RANGE SCAN          | T2_IDX |     1 |       |     1 |

|   5 |   TABLE ACCESS BY INDEX ROWID| T2     |     1 |    15 |     1 |

   3 - filter("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS

   4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")

        323  consistent gets

下面來根據sql_id來進行調優,試試sql_profile給出的見解。先從緩存中查出剛才執行的sql語句。

SQL> select sql_id,sql_text from v$sql where sql_text like '%t1.object_name%'

  2  /

SQL_ID

。。。。

4zbqykx89yc8v

select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id

2pxr40u2zm0ja

select sql_id,sql_text from v$sql where sql_text like '%t1.object_name%'

然後運作下面的存儲過程,執行sqltune task.

SQL> var tuning_task varchar2(100);  

SQL>  DECLARE  

       l_sql_id v$session.prev_sql_id%TYPE;  

   l_tuning_task VARCHAR2(30);  

 BEGIN  

   l_sql_id:='4zbqykx89yc8v';  

   l_tuning_task := dbms_sqltune.create_tuning_task(sql_id => l_sql_id);  

   :tuning_task:=l_tuning_task;  

   dbms_sqltune.execute_tuning_task(l_tuning_task);  

   dbms_output.put_line(l_tuning_task);  

 END;

/  

檢視task的name

SQL> print tuning_task;

TUNING_TASK

--------------------------------------------------------------------------------------------------------------------------------

TASK_12352

如果sql語句本身不複雜,涉及的表不大的話,執行是很快的。如下檢視報告。

SQL> set long 99999

SQL>  col comments format a200

SQL>  SELECT dbms_sqltune.report_tuning_task(:tuning_task)COMMENTS FROM dual;                                                     

COMMENTS

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GENERAL INFORMATION SECTION

-------------------------------------------------------------------------------

Tuning Task Name   : TASK_12352

Tuning Task Owner  : N1

Workload Type      : Single SQL Statement

Scope              : COMPREHENSIVE

Time Limit(seconds): 1800

Completion Status  : COMPLETED

Started at         : 07/10/2014 15:04:18

Completed at       : 07/10/2014 15:04:20

Schema Name: N1

SQL ID     : 4zbqykx89yc8v

SQL Text   : select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%'

             and t1.object_id=t2.object_id

FINDINGS SECTION (1 finding)

1- SQL Profile Finding (see explain plans section below)

  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit: 92.9%)

  -----------------------------------------

  - Consider accepting the recommended SQL profile.

    execute dbms_sqltune.accept_sql_profile(task_name => 'TASK_12352',task_owner => 'N1', replace => TRUE);

  Validation results

  ------------------

  The SQL profile was tested by executing both its plan and the original plan

  and measuring their respective execution statistics. A plan may have been

  only partially executed if the other could be run to completion in less time.

                           Original Plan  With SQL Profile  % Improved

                           -------------  ----------------  ----------

  Completion Status:            COMPLETE          COMPLETE

  Elapsed Time (s):             .042304           .006329      85.03 %

  CPU Time (s):                 .042293           .006399      84.86 %

  User I/O Time (s):                  0                 0

  Buffer Gets:                     4475               317      92.91 %

  Physical Read Requests:             0                 0

  Physical Write Requests:            0                 0

  Physical Read Bytes:                0                 0

  Physical Write Bytes:               0                 0

  Rows Processed:                    26                26

  Fetches:                           26                26

  Executions:                         1                 1

  Notes

  -----

  1. Statistics for the original plan were averaged over 10 executions.

  2. Statistics for the SQL profile plan were averaged over 10 executions.

EXPLAIN PLANS SECTION

1- Original With Adjusted Cost

------------------------------

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT   |      |    26 |  1196 |   796   (1)| 00:00:10 |

|*  1 |  HASH JOIN         |      |    26 |  1196 |   796   (1)| 00:00:10 |

|*  2 |   TABLE ACCESS FULL| T1   |    26 |   806 |    47   (3)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| T2   |   269K|  3952K|   748   (1)| 00:00:09 |

2- Using SQL Profile

--------------------

---------------------------------------------------------------------------------------

| Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     |

|   0 | SELECT STATEMENT             |        |    26 |  1196 |    49   (0)| 00:00:01 |

|   1 |  NESTED LOOPS                |        |       |       |            |          |

|   2 |   NESTED LOOPS               |        |    26 |  1196 |    49   (0)| 00:00:01 |

|*  3 |    TABLE ACCESS FULL         | T1     |    26 |   806 |    47   (3)| 00:00:01 |

|*  4 |    INDEX RANGE SCAN          | T2_IDX |     1 |       |     1   (0)| 00:00:01 |

|   5 |   TABLE ACCESS BY INDEX ROWID| T2     |     1 |    15 |     1   (0)| 00:00:01 |

   3 - filter("T1"."OBJECT_NAME" LIKE '%T1%' AND "T1"."OBJECT_NAME" IS NOT

              NULL)

可以從報告看出,改進确實是很客觀的,提升了90%以上。

來簡單驗證一下,先得accept 一下。

SQL>  execute dbms_sqltune.accept_sql_profile(task_name => 'TASK_12352',task_owner => 'N1', replace => TRUE);

PL/SQL procedure successfully completed.  

再來查詢一下,看看是否啟用了profile

SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id

 /

   - SQL profile "SYS_SQLPROF_01471f52938e0000" used for this statement

         34  recursive calls

          1  db block gets

        338  consistent gets

          3  physical reads

        196  redo size

          1  sorts (memory)

再來看看如果改動了sql語句,多加了些空格,看看profile還能不能正常啟用。

SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=    t2.object_id

Elapsed: 00:00:00.02

--------------------------------------------------

          0  recursive calls

        530  bytes received via SQL*Net from client

可以看到,還是正常啟用了。另外,庫裡的cursor_sharing參數如下。

SQL> show parameter cursor

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

cursor_bind_capture_destination      string      memory+disk

cursor_sharing                       string      EXACT

是以在使用中,對于sql調優來說還是可以嘗試使用sql_profile的,确實提供了不少的知識集。