执行计划中与分区相关的OP介绍
来源:互联网 发布:js查找最大值 编辑:程序博客网 时间:2024/05/01 16:48
在公司整理业务库性能不佳的SQL语句时碰到了较多对分区表的查询语句,在执行计划中发现很多语句都对整个分区表进行扫描,而且大部分还是走的TAF(Table Access Full),因此,这里就对分区表操作时会出现的一些执行计划OP做个介绍
[oracle@ora11g ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Sat Oct 31 22:44:31 2015
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 835104768 bytes
Fixed Size 2257840 bytes
Variable Size 507513936 bytes
Database Buffers 322961408 bytes
Redo Buffers 2371584 bytes
Database mounted.
Database opened.
--创建测试分区表zlm
SQL> create table zlm partition by range(object_id)
(partition p1 values less than(15000),
partition p2 values less than(30000),
partition p3 values less than(45000),
partition p4 values less than(60000),
partition p_max values less than(maxvalue))
as select * from dba_objects; 2 3 4 5 6 7
Table created.
SQL> select count(*) from zlm;
COUNT(*)
----------
86978
SQL> select object_id,object_type from zlm where object_name='ZLM';
OBJECT_ID OBJECT_TYPE
---------- -------------------
88862 TABLE PARTITION
88863 TABLE PARTITION
88861 TABLE PARTITION
88860 TABLE PARTITION
88859 TABLE PARTITION
88858 TABLE
6 rows selected.
--在分区表上创建本地分区索引
SQL> create index ind_zlm_o_name on zlm(object_name) local;
Index created.
SQL> set autot trace exp
SQL> select * from zlm where object_name='ZLM';
Execution Plan
----------------------------------------------------------
Plan hash value: 1634303508
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 1242 |10 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL | | 6 | 1242 |10 (0)| 00:00:01 | 1 | 5 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| ZLM | 6 | 1242 |10 (0)| 00:00:01 | 1 | 5 |
|* 3 | INDEX RANGE SCAN | IND_ZLM_O_NAME | 6 | | 6 (0)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("OBJECT_NAME"='ZLM')
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE ALL:
表示扫描所有分区,此处是第1-5个分区都被扫描了一遍,才得到查询结果。由于在object_name列上有一个本地分区索引,并且是非唯一记录,因此还走了一个IRS。
SQL> select * from zlm where object_id=18000;
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 414 | 61(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 2 | 414 | 61(0)| 00:00:01 | 2 | 2 |
|* 2 | TABLE ACCESS FULL | ZLM | 2 | 414 | 61(0)| 00:00:01 | 2 | 2 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=18000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE SINGLE:
表示只扫描单个分区,这里Pstart和Pstop的值都为2,说明只对第2个分区进行了扫描,因为oracle的cbo会根据where过滤条件中的分区键值判断只扫描需要访问的分区,对于不需要的分区不会访问,这个特性叫做partition purging。由于object_id上未建立分区索引,因此只能走TAF。
SQL> select * from zlm where object_id=88858 and object_name='ZLM';
Execution Plan
----------------------------------------------------------
Plan hash value: 480976975
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 |621 | 4 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE | | 3 |621 | 4 (0)| 00:00:01 | 5 | 5 |
|* 2 | TABLE ACCESS BY LOCAL INDEX ROWID| ZLM | 3 | 621 | 4 (0)| 00:00:01 | 5 | 5 |
|* 3 | INDEX RANGE SCAN | IND_ZLM_O_NAME | 4 | | 1 (0)| 00:00:01 | 5 | 5 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=88858)
3 - access("OBJECT_NAME"='ZLM')
Note
-----
- dynamic sampling used for this statement (level=2)
同样地,当指定的object_id落在第5个分区范围之内时,也只扫描了第5个分区。由于where条件中的object_name列上有索引,所以这次就不走TAF了,而是走IRS。
SQL> select * from zlm where object_id in (4000,8000,16000,32000);
Execution Plan
----------------------------------------------------------
Plan hash value: 419480214
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 2070 | 176(2)| 00:00:03 | | |
| 1 | PARTITION RANGE INLIST| | 10 | 2070 | 176(2)| 00:00:03 |KEY(I) |KEY(I) |
|* 2 | TABLE ACCESS FULL | ZLM | 10 | 2070 | 176(2)| 00:00:03 |KEY(I) |KEY(I) |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=4000 OR "OBJECT_ID"=8000 OR "OBJECT_ID"=16000 OR
"OBJECT_ID"=32000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE INLIST:
当分区关键字存在多个可选值时,比较明显的是查询中有in(n1,n2,n3...)和par_key=n1 or par_key=n2。注意,这里的执行计划走的是PARTITION RANGE INLIST,而且Pstart和Pstop都是用的KEY(I),不过这并不代表只扫描了一个分区,而是扫描了3个分区,其中4000和8000属于第1个分区,16000属于第2个分区,32000属于第3个分区。
SQL> select * from zlm where object_id in (8000);
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 414 | 53(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 2 | 414 | 53(0)| 00:00:01 | 1 | 1 |
|* 2 | TABLE ACCESS FULL | ZLM | 2 | 414 | 53(0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=8000)
Note
-----
- dynamic sampling used for this statement (level=2)
注意,以上尽管是inlist格式的查询,但只给了一个值,因此依旧出现了PARTITION RANGE SINGLE
SQL> select * from zlm where object_id>15000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2128087405
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows| Bytes | Cost (%CPU)| Time| Pstart| Pstop |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT || 84438 | 16M| 295 (4)| 00:00:04 |||
| 1 | PARTITION RANGE ITERATOR|| 84438 | 16M| 295 (4)| 00:00:04 | 2 | 5 |
|* 2 | TABLE ACCESS FULL | ZLM| 84438 | 16M| 295 (4)| 00:00:04 | 2 | 5 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID">15000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE ITERATOR:
表示多个分区迭代扫描,当cbo需要扫描多个连续的分区时就会出现,Pstart和Pstop为需要扫描的分区,此处扫描的分区为2-5,一共扫描了4个分区。同样,由于这里where条件中的object_id上没有索引,因此走了TAF。
SQL> select * from zlm where object_id<15000;
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 13285 | 2685K| 53(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 13285 | 2685K| 53(0)| 00:00:01 | 1 | 1 |
| 2 | TABLE ACCESS FULL | ZLM | 13285 | 2685K| 53(0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
一旦需要查询的记录落在单一的分区内,PARTITION RANGE ITERATOR就会又变为PARTITION RANGE SINGLE,此处只需扫描分区1就可以满足查询需求了。
SQL> select * from zlm where object_id<8000 and object_id>32000;
Execution Plan
----------------------------------------------------------
Plan hash value: 3446828199
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 0(0)| | | |
|* 1 | FILTER | | | | | | | |
| 2 | PARTITION RANGE EMPTY| | 1 | 207 | 53(0)| 00:00:01 |INVALID|INVALID|
|* 3 | TABLE ACCESS FULL | ZLM | 1 | 207 | 53(0)| 00:00:01 |INVALID|INVALID|
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NULL IS NOT NULL)
3 - filter("OBJECT_ID"<8000 AND "OBJECT_ID">32000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE EMPTY:
表示cbo根据统计信息和sql语句,得出该表所对应的分区不存在任何符合查询的结果集。通常在SQL语句的业务逻辑出现问题时产生,因为同时满足object id既小于8000又大于18000的记录是不存在的。
--创建分区表zlm2
SQL> create table zlm2 partition by range(object_id)
2 (partition p1 values less than(15000),
partition p2 values less than(30000),
partition p3 values less than(45000),
partition p4 values less than(60000))
as select * from dba_objects where object_id<60000; 3 4 5 6
Table created.
SQL> select * from zlm2 where object_id>=60000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2767703983
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |207 | 53 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE EMPTY| | 1 |207 | 53 (0)| 00:00:01 |INVALID|INVALID|
|* 2 | TABLE ACCESS FULL | ZLM2 | 1 |207 | 53 (0)| 00:00:01 |INVALID|INVALID|
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID">=60000)
Note
-----
- dynamic sampling used for this statement (level=2)
显然,此时对于查询object id大于等于60000的记录尽管没有逻辑上的错误,但是由于在创建分区表zlm2时并未将这部分数据包含在分区表内,对于该分区表而言,所查询的数据依然是不存在的,因此依然会出现PARTITION RANGE EMPTY,Pstart和Pstop的值也都是INVALID的
那么我们把之前的那条不符合逻辑的SQL查询语句中的and换成or又会如何呢?
SQL> select * from zlm where object_id<8000 or object_id>32000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2323138327
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 58782 | 11M| 287 (3)| 00:00:04 | | |
| 1 | PARTITION RANGE OR| | 58782 | 11M| 287 (3)| 00:00:04 |KEY(OR)|KEY(OR)|
|* 2 | TABLE ACCESS FULL| ZLM | 58782 | 11M| 287 (3)| 00:00:04 |KEY(OR)|KEY(OR)|
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"<8000 OR "OBJECT_ID">32000)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL>
PARTITION RANGE OR:
表示where条件中存在了or运算,并且cbo得出这些运算需要跨越多个不连续的分区,Pstart| Pstop中出现了KEY(OR)的值,它应该跟PARTITION RANGE INLIST中的key(I)一样,也是一个变化的值,所以这里扫描的分区数量具有不确切性。
以上就是对于在访问分区表进行查询时,可能在执行计划中出现的各种OP操作,希望对大家在分析分区表的执行计划时能带来一些帮助。
[oracle@ora11g ~]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Sat Oct 31 22:44:31 2015
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 835104768 bytes
Fixed Size 2257840 bytes
Variable Size 507513936 bytes
Database Buffers 322961408 bytes
Redo Buffers 2371584 bytes
Database mounted.
Database opened.
--创建测试分区表zlm
SQL> create table zlm partition by range(object_id)
(partition p1 values less than(15000),
partition p2 values less than(30000),
partition p3 values less than(45000),
partition p4 values less than(60000),
partition p_max values less than(maxvalue))
as select * from dba_objects; 2 3 4 5 6 7
Table created.
SQL> select count(*) from zlm;
COUNT(*)
----------
86978
SQL> select object_id,object_type from zlm where object_name='ZLM';
OBJECT_ID OBJECT_TYPE
---------- -------------------
88862 TABLE PARTITION
88863 TABLE PARTITION
88861 TABLE PARTITION
88860 TABLE PARTITION
88859 TABLE PARTITION
88858 TABLE
6 rows selected.
--在分区表上创建本地分区索引
SQL> create index ind_zlm_o_name on zlm(object_name) local;
Index created.
SQL> set autot trace exp
SQL> select * from zlm where object_name='ZLM';
Execution Plan
----------------------------------------------------------
Plan hash value: 1634303508
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 1242 |10 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL | | 6 | 1242 |10 (0)| 00:00:01 | 1 | 5 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| ZLM | 6 | 1242 |10 (0)| 00:00:01 | 1 | 5 |
|* 3 | INDEX RANGE SCAN | IND_ZLM_O_NAME | 6 | | 6 (0)| 00:00:01 | 1 | 5 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("OBJECT_NAME"='ZLM')
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE ALL:
表示扫描所有分区,此处是第1-5个分区都被扫描了一遍,才得到查询结果。由于在object_name列上有一个本地分区索引,并且是非唯一记录,因此还走了一个IRS。
SQL> select * from zlm where object_id=18000;
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 414 | 61(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 2 | 414 | 61(0)| 00:00:01 | 2 | 2 |
|* 2 | TABLE ACCESS FULL | ZLM | 2 | 414 | 61(0)| 00:00:01 | 2 | 2 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=18000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE SINGLE:
表示只扫描单个分区,这里Pstart和Pstop的值都为2,说明只对第2个分区进行了扫描,因为oracle的cbo会根据where过滤条件中的分区键值判断只扫描需要访问的分区,对于不需要的分区不会访问,这个特性叫做partition purging。由于object_id上未建立分区索引,因此只能走TAF。
SQL> select * from zlm where object_id=88858 and object_name='ZLM';
Execution Plan
----------------------------------------------------------
Plan hash value: 480976975
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 |621 | 4 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE | | 3 |621 | 4 (0)| 00:00:01 | 5 | 5 |
|* 2 | TABLE ACCESS BY LOCAL INDEX ROWID| ZLM | 3 | 621 | 4 (0)| 00:00:01 | 5 | 5 |
|* 3 | INDEX RANGE SCAN | IND_ZLM_O_NAME | 4 | | 1 (0)| 00:00:01 | 5 | 5 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=88858)
3 - access("OBJECT_NAME"='ZLM')
Note
-----
- dynamic sampling used for this statement (level=2)
同样地,当指定的object_id落在第5个分区范围之内时,也只扫描了第5个分区。由于where条件中的object_name列上有索引,所以这次就不走TAF了,而是走IRS。
SQL> select * from zlm where object_id in (4000,8000,16000,32000);
Execution Plan
----------------------------------------------------------
Plan hash value: 419480214
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 2070 | 176(2)| 00:00:03 | | |
| 1 | PARTITION RANGE INLIST| | 10 | 2070 | 176(2)| 00:00:03 |KEY(I) |KEY(I) |
|* 2 | TABLE ACCESS FULL | ZLM | 10 | 2070 | 176(2)| 00:00:03 |KEY(I) |KEY(I) |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=4000 OR "OBJECT_ID"=8000 OR "OBJECT_ID"=16000 OR
"OBJECT_ID"=32000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE INLIST:
当分区关键字存在多个可选值时,比较明显的是查询中有in(n1,n2,n3...)和par_key=n1 or par_key=n2。注意,这里的执行计划走的是PARTITION RANGE INLIST,而且Pstart和Pstop都是用的KEY(I),不过这并不代表只扫描了一个分区,而是扫描了3个分区,其中4000和8000属于第1个分区,16000属于第2个分区,32000属于第3个分区。
SQL> select * from zlm where object_id in (8000);
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 414 | 53(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 2 | 414 | 53(0)| 00:00:01 | 1 | 1 |
|* 2 | TABLE ACCESS FULL | ZLM | 2 | 414 | 53(0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"=8000)
Note
-----
- dynamic sampling used for this statement (level=2)
注意,以上尽管是inlist格式的查询,但只给了一个值,因此依旧出现了PARTITION RANGE SINGLE
SQL> select * from zlm where object_id>15000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2128087405
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows| Bytes | Cost (%CPU)| Time| Pstart| Pstop |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT || 84438 | 16M| 295 (4)| 00:00:04 |||
| 1 | PARTITION RANGE ITERATOR|| 84438 | 16M| 295 (4)| 00:00:04 | 2 | 5 |
|* 2 | TABLE ACCESS FULL | ZLM| 84438 | 16M| 295 (4)| 00:00:04 | 2 | 5 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID">15000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE ITERATOR:
表示多个分区迭代扫描,当cbo需要扫描多个连续的分区时就会出现,Pstart和Pstop为需要扫描的分区,此处扫描的分区为2-5,一共扫描了4个分区。同样,由于这里where条件中的object_id上没有索引,因此走了TAF。
SQL> select * from zlm where object_id<15000;
Execution Plan
----------------------------------------------------------
Plan hash value: 636735399
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 13285 | 2685K| 53(0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE| | 13285 | 2685K| 53(0)| 00:00:01 | 1 | 1 |
| 2 | TABLE ACCESS FULL | ZLM | 13285 | 2685K| 53(0)| 00:00:01 | 1 | 1 |
-----------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
一旦需要查询的记录落在单一的分区内,PARTITION RANGE ITERATOR就会又变为PARTITION RANGE SINGLE,此处只需扫描分区1就可以满足查询需求了。
SQL> select * from zlm where object_id<8000 and object_id>32000;
Execution Plan
----------------------------------------------------------
Plan hash value: 3446828199
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 0(0)| | | |
|* 1 | FILTER | | | | | | | |
| 2 | PARTITION RANGE EMPTY| | 1 | 207 | 53(0)| 00:00:01 |INVALID|INVALID|
|* 3 | TABLE ACCESS FULL | ZLM | 1 | 207 | 53(0)| 00:00:01 |INVALID|INVALID|
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NULL IS NOT NULL)
3 - filter("OBJECT_ID"<8000 AND "OBJECT_ID">32000)
Note
-----
- dynamic sampling used for this statement (level=2)
PARTITION RANGE EMPTY:
表示cbo根据统计信息和sql语句,得出该表所对应的分区不存在任何符合查询的结果集。通常在SQL语句的业务逻辑出现问题时产生,因为同时满足object id既小于8000又大于18000的记录是不存在的。
--创建分区表zlm2
SQL> create table zlm2 partition by range(object_id)
2 (partition p1 values less than(15000),
partition p2 values less than(30000),
partition p3 values less than(45000),
partition p4 values less than(60000))
as select * from dba_objects where object_id<60000; 3 4 5 6
Table created.
SQL> select * from zlm2 where object_id>=60000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2767703983
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |207 | 53 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE EMPTY| | 1 |207 | 53 (0)| 00:00:01 |INVALID|INVALID|
|* 2 | TABLE ACCESS FULL | ZLM2 | 1 |207 | 53 (0)| 00:00:01 |INVALID|INVALID|
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID">=60000)
Note
-----
- dynamic sampling used for this statement (level=2)
显然,此时对于查询object id大于等于60000的记录尽管没有逻辑上的错误,但是由于在创建分区表zlm2时并未将这部分数据包含在分区表内,对于该分区表而言,所查询的数据依然是不存在的,因此依然会出现PARTITION RANGE EMPTY,Pstart和Pstop的值也都是INVALID的
那么我们把之前的那条不符合逻辑的SQL查询语句中的and换成or又会如何呢?
SQL> select * from zlm where object_id<8000 or object_id>32000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2323138327
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 58782 | 11M| 287 (3)| 00:00:04 | | |
| 1 | PARTITION RANGE OR| | 58782 | 11M| 287 (3)| 00:00:04 |KEY(OR)|KEY(OR)|
|* 2 | TABLE ACCESS FULL| ZLM | 58782 | 11M| 287 (3)| 00:00:04 |KEY(OR)|KEY(OR)|
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OBJECT_ID"<8000 OR "OBJECT_ID">32000)
Note
-----
- dynamic sampling used for this statement (level=2)
SQL>
PARTITION RANGE OR:
表示where条件中存在了or运算,并且cbo得出这些运算需要跨越多个不连续的分区,Pstart| Pstop中出现了KEY(OR)的值,它应该跟PARTITION RANGE INLIST中的key(I)一样,也是一个变化的值,所以这里扫描的分区数量具有不确切性。
以上就是对于在访问分区表进行查询时,可能在执行计划中出现的各种OP操作,希望对大家在分析分区表的执行计划时能带来一些帮助。
0 0
- 执行计划中与分区相关的OP介绍
- zend_execute中op的执行
- 21. OP-TEE中TA与CA执行流程-------libteec介绍
- 20. OP-TEE中TA与CA执行流程-------CA部分的代码篇
- Oracle分区执行计划
- 23. OP-TEE中TA与CA执行流程-------tee-supplicant(TA请求具体请求的处理)
- Oracle执行计划的相关概念
- Oracle执行计划的相关概念
- Oracle执行计划的相关概念
- oracle 清除相关对象的执行计划
- Oracle执行计划的相关概念
- ORACLE获得执行计划的相关视图
- [转]Oracle执行计划的相关概念
- oracle 分区 索引 执行计划
- mysql 执行计划走分区
- 确认执行计划中分区号对应的分区
- 执行计划相关SQL
- oracle执行计划相关
- SDWebImage详解
- Android中HorizontalScrollView的使用
- Java语言入门
- 翻译了一半的文,明天补
- ubuntu jdk1.8
- 执行计划中与分区相关的OP介绍
- HDOJ 1286 找新朋友(欧拉函数模板)
- javascript中讨论关联数组和对象的区别
- LightOJ - 1071 Baker Vai(记忆化搜索)
- java基础——static深入理解
- PIC+DS18B20+LCD设计及程序过程中的问题
- [Django与表单]先来了解HttpRequest对象
- Game(bc模拟题)
- 英语让路---2015年10月英语月总