情境:
我有一个包含568801行的表和列TIM_RECEPT
(TIMESTAMP)上的索引。索引生成为TRUNC("TIM_RECEPT")
。
此表格于4月19日填写此查询:
INSERT INTO MY_TABLE SELECT <fields> FROM <tables>
接下来的几天表格已加载:
INSERT INTO MY_TABLE SELECT <fields>
FROM <tables> WHERE alias.tim_recept > TRUNC(SYSDATE -1)
问题:
当我在解释计划中使用索引时,请返回:
EXPLAIN PLAN FOR
select *
from MY_TABLE
where trunc(TIM_RECEPT) >= TO_DATE('22/11/2017', 'DD-MM-YYYY')
and trunc(TIM_RECEPT) <= TO_DATE('26/04/2018', 'DD-MM-YYYY')
;
select * from table(dbms_xplan.display);
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 42112 | 13M| 8690 (1)| 00:01:45 |
| 1 | TABLE ACCESS BY INDEX ROWID| MY_TABLE | 42112 | 13M| 8690 (1)| 00:01:45 |
|* 2 | INDEX RANGE SCAN | IMYTABLE1 | 42112 | | 114 (0)| 00:00:02 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(TRUNC(INTERNAL_FUNCTION("TIM_RECEPT"))>=TO_DATE(' 2017-11-22
00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
TRUNC(INTERNAL_FUNCTION("TIM_RECEPT"))<=TO_DATE(' 2018-04-26 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
但是如果我更改初始日期并休息一天,则不使用索引:
EXPLAIN PLAN FOR
select *
from MY_TABLE
where trunc(TIM_RECEPT) >= TO_DATE('21/11/2017', 'DD-MM-YYYY')
and trunc(TIM_RECEPT) <= TO_DATE('26/04/2018', 'DD-MM-YYYY')
;
select * from table(dbms_xplan.display);
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 42395 | 14M| 8739 (1)| 00:01:45 |
|* 1 | TABLE ACCESS FULL| MY_TABLE | 42395 | 14M| 8739 (1)| 00:01:45 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRUNC(INTERNAL_FUNCTION("TIM_RECEPT"))>=TO_DATE('
2017-11-21 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
TRUNC(INTERNAL_FUNCTION("TIM_RECEPT"))<=TO_DATE(' 2018-04-26 00:00:00',
'syyyy-mm-dd hh24:mi:ss'))
关于这个问题的任何想法?
答案 0 :(得分:2)
Oracle优化器不使用索引i snot必要的问题。这是一个问题
当FULL TABLE SCAN
访问所消耗的资源(在大多数情况下已用时间)高于a {
使用INDEX ACCESS
的替代执行计划(您不是明确状态)。
从优化器的角度出发,两个执行计划都很好并且导致大致相同的时间。
因此,如果这些查询的经验不同,实际经过的时间与估计(01:45)有很大不同 您(或您的DBA))应采取以下步骤:
1)验证表的优化程序统计信息
过时的统计信息可能会欺骗优化器。特别是如果你收集小桌子上的统计数据和 插入大量记录。
2)验证优化程序参数和系统统计信息
某些参数DB_FILE_MULTIBLOCK_READ_COUNT与FTS
和INDEX ACCES
之间的选择密切相关。
类似对System Statistics设置有效。
最后备注
要访问大表的非平凡部分(例如100天内50个),不一定是INDEX ACCESS
的用例。检查分区功能,(range partitioning)
是为这种访问而设计的。