建立测试表,一个非常简单的分区表
CREATE TABLE SCOTT.T_NEW_1 (ID, TIME,NAME) PARTITION BY RANGE (TIME)
(PARTITION P1 VALUES LESS THAN (TO_DATE('2015-7-1', 'YYYY-MM-DD')),
PARTITION P2 VALUES LESS THAN (TO_DATE('2016-1-1', 'YYYY-MM-DD')),
PARTITION P3 VALUES LESS THAN (TO_DATE('2017-7-1', 'YYYY-MM-DD')),
PARTITION P4 VALUES LESS THAN (MAXVALUE))
AS SELECT object_id, created,OBJECT_NAME FROM dba_objects;
创建一个分区索引
create index SCOTT.T_NEW_IDX_2 on SCOTT.T_NEW_1 (time) local;
Sql文本如下:
select /*+ gather_plan_statistics index(T_NEW_1 T_NEW_IDX_2) */
count(1) from SCOTT.T_NEW_1
where time >= to_date('2013/8/01 00:00:00','yyyy-mm-dd hh24:mi:ss')
and time <= to_date('2013/8/31 23:59:59','yyyy-mm-dd hh24:mi:ss');
该Sql的执行计划如下:
Plan hash value: 2028335963
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 231 (1)| 00:00:03 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION RANGE SINGLE| | 86200 | 673K| 231 (1)| 00:00:03 | 1 | 1 |
|* 3 | INDEX RANGE SCAN | T_NEW_IDX_2 | 86200 | 673K| 231 (1)| 00:00:03 | 1 | 1 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("TIME">=TO_DATE(' 2013-08-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"TIME"<=TO_DATE(' 2013-08-31 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
此时我们也看到,这个时候是走了PARTITION RANGE SINGLE,这没有问题
但是当我把两个参数用绑定变量的方式传入的时候,执行计划就发生了改变
先定义两个绑定变量
SQL> var b1 varchar2(30);
SQL> var b2 varchar2(30);
SQL> exec :b1 := '2013/8/01 00:00:00';
SQL> exec :b2 := '2013/8/31 23:59:59';
Sql文本如下
select /*+ gather_plan_statistics index(T_NEW_1 T_NEW_IDX_2) */
count(1) from SCOTT.T_NEW_1
where time >= to_date(:b1,'yyyy-mm-dd hh24:mi:ss')
and time <= to_date(:b2,'yyyy-mm-dd hh24:mi:ss');
执行计划如下:
Plan hash value: 2829989424
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.02 | 230 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.02 | 230 |
|* 2 | FILTER | | 1 | | 86200 |00:00:00.04 | 230 |
| 3 | PARTITION RANGE ITERATOR| | 1 | 86200 | 86200 |00:00:00.03 | 230 |
|* 4 | INDEX RANGE SCAN | T_NEW_IDX_2 | 1 | 86200 | 86200 |00:00:00.01 | 230 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_DATE(:B2,'yyyy-mm-dd hh24:mi:ss')>=TO_DATE(:B1,'yyyy-mm-dd hh24:mi:ss'))
4 - access("TIME">=TO_DATE(:B1,'yyyy-mm-dd hh24:mi:ss') AND
"TIME"<=TO_DATE(:B2,'yyyy-mm-dd hh24:mi:ss'))
注意:我这个例子所在的环境中,绑定变量窥探功能是开启的
这里执行计划就出现了变化,变成了PARTITION RANGE ITERATOR,走了分区迭代,那么为什么我这儿明明指定了一个分区,他还是会走分区迭代的执行计划呢
而且本菜鸟也看了一下生成的10053,里面所使用的统计信息确实也是分区统计信息,而不是全局统计信息
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T_NEW Alias: D Partition [0]
#Rows: 86200 #Blks: 232 AvgRowLen: 13.00 ChainCnt: 0.00
#Rows: 86200 #Blks: 232 AvgRowLen: 13.00 ChainCnt: 0.00
Index Stats::
Index: IDX_TIME Col#: 2 PARTITION [0]
LVLS: 1 #LB: 229 #DK: 861 LB/K: 1.00 DB/K: 1.00 CLUF: 250.00
LVLS: 1 #LB: 229 #DK: 861 LB/K: 1.00 DB/K: 1.00 CLUF: 250.00
User hint to use this index
ALL PARTITIONS USABLE
本菜鸟也亲测过这两个执行计划对应的消耗,完全是一模一样的,按理应该,走分区迭代的执行计划所消耗的逻辑读应该要比走分区裁剪的执行计划的逻辑读要多,但是通过set autotrace on所看到的逻辑读完全是一模一样的。
那这里为什么会出现这种现象呢,这种现象有什么弊端呢,请各路大神一定帮小弟解答呀!!!!!