Oracle_绑定变量窥探测试

绑定变量窥探受隐含参数:_optim_peek_user_binds的限制,自9i之后改参数默认为True,为自动开启状态:

查询sql

SQL> col name for a50
SQL> col value for a10
SQL> col description for a100
SQL> select a.ksppinm name, b.ksppstvl value, a.ksppdesc description from x$ksppi a, x$ksppcv b where a.indx = b.indx
  2  and a.ksppinm like '%_optim_peek_user_binds%';


NAME                                               VALUE      DESCRIPTION
-------------------------------------------------- ---------- ---------------------------------------------------------
_optim_peek_user_binds                             TRUE       enable peeking of user binds

接下来,我们测试一个绑定变量窥探的示例:

1、创建测试表t1

      create table sdxj.t1 as select * from dba_objects;
2、创建索引
      create index idx_t1 on sdxj.t1 (object_id);
3、对表进行分析
       exec dbms_stats.gather_table_stats(ownname => 'SDXJ',tabname => 'T1',estimate_percent => 100,CASCADE => TRUE,method_opt => 'for all columns size 1',degree => 8,no_invalidate    => FALSE);

4、执行以下两个sql

      4.1、SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999  AND  1000;

      4.2、SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999  AND  6000;

      4.3、查看sql执行情况

SQL> SELECT  SQL_TEXT,SQL_ID,VERSION_COUNT ,executions FROM V$SQLAREA WHERE SQL_TEXT LIKE 'SELECT COUNT(*) FROM SDXJ.T1%';

SQL_TEXT                                                               SQL_ID               VERSION_COUNT EXECUTIONS
---------------------------------------------------------------------- -------------------- ------------- ----------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 1000      gxgb577ncwrm2                 1     1
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 60000     6d2d6y357kfws                 1     1

SQL> col plan_table_output for a200
SQL> set long 900
SQL> set pages 800
SQL> SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('gxgb577ncwrm2','0','advanced'));

----sql1 执行计划----
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
SQL_ID  gxgb577ncwrm2, child number 0
-------------------------------------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 1000

Plan hash value: 1970818898

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |       |       |     2 (100)|          |
|   1 |  SORT AGGREGATE   |        |     1 |     5 |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_T1 |     3 |    15 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / T1@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

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

   2 - access("OBJECT_ID">=999 AND "OBJECT_ID"<=1000)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

Note
-----
   - SQL plan baseline SQL_PLAN_f02470f3q2mcga9a6a0a8 used for this statement

已选择48行。

---sql2 执行计划---

Plan hash value: 2101382132
--------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |       |       |    46 (100)|          |
|   1 |  SORT AGGREGATE       |        |     1 |     5 |            |          |
|*  2 |   INDEX FAST FULL SCAN| IDX_T1 | 54911 |   268K|    46   (3)| 00:00:01 |
--------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T1@SEL$1

Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_FFS(@"SEL$1" "T1"@"SEL$1" ("T1"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("OBJECT_ID"<=60000 AND "OBJECT_ID">=999))

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

已选择44行。


现在我们将上述两个SQL进行改造,使其可以用绑定变量的形式。

SQL> var x number;
SQL> var y number;
SQL> exec :x :=999
    PL/SQL 过程已成功完成。
SQL> exec :y :=1000
   PL/SQL 过程已成功完成。

---执行查询sql

SQL> SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y;

  COUNT(*)
----------
         2
---查询sql执行情况
SQL> SELECT  SQL_TEXT,SQL_ID,VERSION_COUNT ,executions FROM V$SQLAREA WHERE SQL_TEXT LIKE 'SELECT COUNT(*) FROM SDXJ.T1%';

SQL_TEXT                                                               SQL_ID               VERSION_COUNT EXECUTIONS
---------------------------------------------------------------------- -------------------- ------------- ----------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y         65r6vbdf4n1vk                            1     1
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 1000      gxgb577ncwrm2                 1     1
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 60000     6d2d6y357kfws                 1     1

----查看执行计划
SQL> SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('65r6vbdf4n1vk','0','advanced'));

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
SQL_ID  65r6vbdf4n1vk, child number 0
-------------------------------------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y

Plan hash value: 2351893609

-----------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |       |       |     2 (100)|          |
|   1 |  SORT AGGREGATE    |        |     1 |     5 |            |          |
|*  2 |   FILTER           |        |       |       |            |          |
|*  3 |    INDEX RANGE SCAN| IDX_T1 |     3 |    15 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   3 - SEL$1 / T1@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :X (NUMBER): 999
   2 - :Y (NUMBER): 1000

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

   2 - filter(:X<=:Y)
   3 - access("OBJECT_ID">=:X AND "OBJECT_ID"<=:Y)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

Note
-----
   - SQL plan baseline SQL_PLAN_b0hdzdb9t6f6911bbd8aa used for this statement

已选择56行。


下面执行第二个sql语句,将y改为60000

SQL> exec :y :=60000

PL/SQL 过程已成功完成。

SQL> SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y;

  COUNT(*)
----------
     58180

SQL> SELECT  SQL_TEXT,SQL_ID,VERSION_COUNT ,executions FROM V$SQLAREA WHERE SQL_TEXT LIKE 'SELECT COUNT(*) FROM SDXJ.T1%';

SQL_TEXT                                                               SQL_ID               VERSION_COUNT EXECUTIONS
---------------------------------------------------------------------- -------------------- ------------- ----------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y         65r6vbdf4n1vk                            1     2
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 1000      gxgb577ncwrm2                 1     1
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN 999 AND 60000     6d2d6y357kfws                 1     1

SQL> SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY_CURSOR('65r6vbdf4n1vk','0','advanced'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------
SQL_ID  65r6vbdf4n1vk, child number 0
-------------------------------------
SELECT COUNT(*) FROM SDXJ.T1 WHERE OBJECT_ID BETWEEN :x AND :y

Plan hash value: 2351893609

-----------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |       |       |     2 (100)|          |
|   1 |  SORT AGGREGATE    |        |     1 |     5 |            |          |
|*  2 |   FILTER           |        |       |       |            |          |
|*  3 |    INDEX RANGE SCAN| IDX_T1 |     3 |    15 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   3 - SEL$1 / T1@SEL$1

Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------
   1 - :X (NUMBER): 999
   2 - :Y (NUMBER): 1000

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:X<=:Y)
   3 - access("OBJECT_ID">=:X AND "OBJECT_ID"<=:Y)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
   1 - (#keys=0) COUNT(*)[22]

Note
-----
   - SQL plan baseline SQL_PLAN_b0hdzdb9t6f6911bbd8aa used for this statement

已选择56行。

SQL>


从上面执行计划可以看出,依然走索引:INDEX RANGE SCAN| IDX_T1 并且绑定变量值仍然为999~1000;

现在,我们在进行另外一个测试。让其走 INDEX FAST FULL SCAN| 索引,测试方法同上,首先创建表T2

采用绑定变量时,首先带入只999 和60000 然后在测试999 h和1000 查看执行计划情况。







你可能感兴趣的:(Oracle,技术分享)