【发布时间】:2019-10-17 00:39:58
【问题描述】:
我正在从分区表的某些分区中选择所有数据(Oracle 11g - 在真实情况下实际更新,但对于示例,选择显示了我想理解的相同行为)。你能解释一下为什么 Oracle 决定使用索引而不是全扫描吗?据我了解,全面扫描将是更智能的访问方法。为什么 Oracle 认为按索引 rowid 批处理的索引范围扫描 + 表访问比分区的完整扫描更智能?
测试表:
CREATE TABLE t_test
(ID NUMBER NOT NULL ENABLE,
PARTITION_NUMBER NUMBER NOT NULL ENABLE,
CREATION_TIMESTAMP DATE DEFAULT SYSDATE NOT NULL ENABLE,
CONSTRAINT PK_t_test PRIMARY KEY (PARTITION_NUMBER, ID) USING INDEX LOCAL
)
PARTITION BY LIST (PARTITION_NUMBER)
(
PARTITION P1 VALUES (1) SEGMENT CREATION IMMEDIATE,
PARTITION P2 VALUES (2) SEGMENT CREATION IMMEDIATE,
PARTITION P3 VALUES (3) SEGMENT CREATION IMMEDIATE,
PARTITION P4 VALUES (4) SEGMENT CREATION IMMEDIATE,
PARTITION P5 VALUES (5) SEGMENT CREATION IMMEDIATE,
PARTITION P6 VALUES (6) SEGMENT CREATION IMMEDIATE,
PARTITION P7 VALUES (7) SEGMENT CREATION IMMEDIATE,
PARTITION P8 VALUES (8) SEGMENT CREATION IMMEDIATE,
PARTITION P9 VALUES (9) SEGMENT CREATION IMMEDIATE
);
从某些分区中选择数据(此示例中没有插入任何内容,但与分区中的数据行为相同):
explain plan for select * from t_test where PARTITION_NUMBER in (2,3,4,5,6,7);
SELECT * FROM TABLE(dbms_xplan.display);
Plan hash value: 3284178661
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 35 | 1 (0)| 00:00:01 | | |
| 1 | INLIST ITERATOR | | | | | | | |
| 2 | PARTITION LIST ITERATOR | | 1 | 35 | 1 (0)| 00:00:01 |KEY(I) |KEY(I) |
| 3 | TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T_TEST | 1 | 35 | 1 (0)| 00:00:01 |KEY(I) |KEY(I) |
|* 4 | INDEX RANGE SCAN | PK_T_TEST | 1 | | 2 (0)| 00:00:01 |KEY(I) |KEY(I) |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("PARTITION_NUMBER"=2 OR "PARTITION_NUMBER"=3 OR "PARTITION_NUMBER"=4 OR "PARTITION_NUMBER"=5 OR
"PARTITION_NUMBER"=6 OR "PARTITION_NUMBER"=7)
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
我不明白为什么它会进行范围扫描...为什么不只是这样(相同的查询但带有完整提示)?为什么它认为在这里使用索引是更好的方法? (即使是 ALL_ROWS 提示也不会改变行为):
explain plan for select /*+ full(t_test) */ * from t_test where PARTITION_NUMBER in (2,3,4,5,6,7);
SELECT * FROM TABLE(dbms_xplan.display);
Plan hash value: 3335595461
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 35 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION LIST INLIST| | 1 | 35 | 2 (0)| 00:00:01 |KEY(I) |KEY(I) |
| 2 | TABLE ACCESS FULL | T_TEST | 1 | 35 | 2 (0)| 00:00:01 |KEY(I) |KEY(I) |
------------------------------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
【问题讨论】:
标签: oracle oracle11g sql-execution-plan