Oracle 索引时间戳

Oracle Index Timestamp

场景:

我有一个包含 568801 行的 table 和 TIM_RECEPT 列上的索引(TIMESTAMP)。索引生成为 TRUNC("TIM_RECEPT").

这个 table 是在 4 月 19 日用这个查询填写的:

INSERT INTO MY_TABLE SELECT <fields> FROM <tables>

接下来几天 table 加载了:

INSERT INTO MY_TABLE SELECT <fields> 
FROM <tables> WHERE alias.tim_recept > TRUNC(SYSDATE -1)

问题:

当我在解释计划中使用索引时,return this:

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'))

对这个问题有什么想法吗?

Oracle 优化器不使用索引的事实我没有必要一个问题。这是一个问题 当 FULL TABLE SCAN 访问所消耗的资源(在大多数情况下是经过的时间)高于 使用 INDEX ACCESS 的替代执行计划(您没有 明确地 声明)。

从优化器的角度来看,两个执行计划都很好并且导致大约相同的时间。

因此,如果这些查询的体验不同,并且实际经过的时间与估计的时间有很大差异 (01:45) 您(或您的 DBA))应该采取以下步骤:

1) 验证 table

的优化器统计信息

过时的统计信息可能会欺骗优化器。特别是如果你收集了一个小 table 的统计数据并且 插入大量记录。

2) 验证优化器参数和系统统计信息

一些参数特别是 DB_FILE_MULTIBLOCK_READ_COUNTFTSINDEX ACCES 之间的选择高度相关。

类似适用于System Statistics设置。

最后备注

要访问大型 table 的非平凡部分(比如 100 天中的 50 个)不需要 INDEX ACCESS 的用例。检查 分区功能 ,其中 (range partitioning) 专为此类访问而设计。