绑定变量窥探受隐含参数:_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 查看执行计划情况。