欢迎进入oracle社区论坛,与200万技术人员互动交流 >>进入
sql> exec :v := 2;
pl/sql 过程已成功完成。
sql> select count(*) from acs_test_tab where record_type = :v;
count(*)
----------
50000
sql> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
plan_table_output
----------------------------------------------------------------------------------------------------
sql_id3rg5r8sghcvb3, child number 0
-------------------------------------
select count(*) from acs_test_tab where record_type = :v
plan hash value: 2957754476
----------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
----------------------------------------------------------------------------------------------------
| 0 | select statement | | | | 136 (100)| |
| 1 | sort aggregate | | 1 | 4 || |
|* 2 | index fast full scan| acs_test_tab_record_type_i | 48031 | 187k| 136 (1)| 00:00:02 |
----------------------------------------------------------------------------------------------------
peeked binds (identified by position):
--------------------------------------
1 - :v (number): 2 --绑定变量窥探,绑定变量会影响最初硬解析的执行计划
predicate information (identified by operation id):
---------------------------------------------------
2 - filter(record_type=:v)
已选择49行。
使用绑定变量窥测的好处是:可以帮助优化器在第一次硬解析时选择最优的执行计划。但是同时这也是其弊端:在第一次硬解析后,后面发生的所有解析都会使用第一次硬解析生成的执行计划,如果数据的分布是均匀的,问题不大,如果数据分布式倾斜的,那么第一次硬解析生成的执行计划未必是最优的,甚至可能是非常糟糕的。例如:
sql> show parameter optimizer_feat
name type value
------------------------------------ ----------- ------------------------------
optimizer_features_enable string 11.2.0.3.1
sql> alter system flush shared_pool;
系统已更改。
sql> var v number;
sql> exec :v := 2;
pl/sql 过程已成功完成。
sql> select count(*) from acs_test_tab where record_type = :v;
count(*)
----------
50000
sql> select * from table(dbms_xplan.display_cursor);
plan_table_output
----------------------------------------------------------------------------------------------------
sql_id3rg5r8sghcvb3, child number 0
-------------------------------------
select count(*) from acs_test_tab where record_type = :v
plan hash value: 2957754476
----------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
----------------------------------------------------------------------------------------------------
| 0 | select statement | | | | 136 (100)| |
| 1 | sort aggregate | | 1 | 4 || |
|* 2 | index fast full scan| acs_test_tab_record_type_i | 48031 | 187k| 136 (1)| 00:00:02 |
----------------------------------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - filter(record_type=:v)
已选择19行。
sql> exec :v := 1
pl/sql 过程已成功完成。
sql> select count(*) from acs_test_tab where record_type = :v;
count(*)
----------
1
sql> select * from table(dbms_xplan.display_cursor);
plan_table_output
----------------------------------------------------------------------------------------------------
sql_id3rg5r8sghcvb3, child number 0
-------------------------------------
select count(*) from acs_test_tab where record_type = :v
plan hash value: 2957754476
----------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
----------------------------------------------------------------------------------------------------
| 0 | select statement | | | | 136 (100)| |
| 1 | sort aggregate | | 1 | 4 || |
|* 2 | index fast full scan| acs_test_tab_record_type_i | 48031 | 187k| 136 (1)| 00:00:02 |
----------------------------------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - filter(record_type=:v)
已选择19行。
sql> select count(*) from acs_test_tab where record_type = 1;
count(*)
----------
1
sql> select * from table(dbms_xplan.display_cursor);
plan_table_output
----------------------------------------------------------------------------------------------------
sql_id1pxm87f6yd0bp, child number 0
-------------------------------------
select count(*) from acs_test_tab where record_type = 1
plan hash value: 2956728990
------------------------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
------------------------------------------------------------------------------------------------
| 0 | select statement | | | | 3 (100)| |
| 1 | sort aggregate | | 1 | 4 | | |
|* 2 | index range scan| acs_test_tab_record_type_i | 1 | 4 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
predicate information (identified by operation id):
---------------------------------------------------
2 - access(record_type=1)
已选择19行。
对于变量v的取值为1的执行计划和采用常量1的执行计划性能差距还是比较大的。
总结:oracle在9i后引入变量窥测技术,该技术对于数据分布均匀的数据是非常合适的,但是对于分布倾斜的数据或者在olap系统中是不建议使用的。
[1] [2]