Sql Oracle索引时间戳

Sql Oracle索引时间戳,sql,oracle,oracle11g,query-performance,Sql,Oracle,Oracle11g,Query Performance,场景: 我有一个568801行的表,在TIM_RECEPT(TIMESTAMP)列上有一个索引。索引生成为TRUNC(“TIM_RECEPT”) 该表于4月19日填写了以下查询: INSERT INTO MY_TABLE SELECT <fields> FROM <tables> 插入到MY_表中从中选择 在接下来的几天内,该表已加载以下内容: INSERT INTO MY_TABLE SELECT <fields> FROM <tables>

场景:

我有一个568801行的表,在
TIM_RECEPT
(TIMESTAMP)列上有一个索引。索引生成为
TRUNC(“TIM_RECEPT”)

该表于4月19日填写了以下查询:

INSERT INTO MY_TABLE SELECT <fields> FROM <tables>
插入到MY_表中从中选择
在接下来的几天内,该表已加载以下内容:

INSERT INTO MY_TABLE SELECT <fields> 
FROM <tables> WHERE alias.tim_recept > TRUNC(SYSDATE -1)
插入我的表格选择
从其中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计划
挑选*
从我的桌子上
其中trunc(TIM接收)>=截止日期('2017年11月22日,'DD-MM-YYYY')
和TRUC(TIM_RECEPT)=截至日期('2017-11-22
00:00:00’,“syyyy mm dd hh24:mi:ss”)和
TRUNC(内部功能(“TIM接收”)=截止日期(“2017年11月21日”、“年-月-日”)
和trunc(TIM_RECEPT)=截止日期('
2017-11-21 00:00:00,“syyyy mm dd hh24:mi:ss”)和

TRUNC(INTERNAL_FUNCTION(“TIM_RECEPT”)Oracle optimizer不使用索引这一事实不一定是个问题。这是个问题 当
全表扫描
访问所消耗的资源(在大多数情况下是经过的时间)高于 使用
索引访问
(您未明确说明)的替代执行计划

从优化器的角度来看,这两个执行计划都很好,并导致几乎相同的时间

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

1)验证表的优化器统计信息

陈旧的统计数据可能会愚弄优化器。尤其是当你在一张小桌子上收集统计数据 这将插入大量记录

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

一些参数与
FTS
索引访问之间的选择非常相关

类似的设置也适用

最后一句话

索引访问
的用例中,不需要访问一个大表的非平凡部分(比如100天中的50个)。检查分区功能,它()
是专为这种访问而设计的。

我想,乐观主义者只是认为额外一天的额外容量(此处以行数表示)已经越过了一个界限,在这个界限中使用索引进行完整扫描更便宜。基于它的统计数据,这可能不是最新的(我们不知道日期分布-是否有额外一天的行)。这并不总是有用的,但是如果您添加使用索引的提示,会报告什么成本?如果您为该表运行
dbms\u stats.gather\u table\u stats()
,计划是否会更改?不相关,但是:您在
to\u date()
调用中指定了格式
'DD-MM-yyyyy'
,但是您提供的日期是
DD/MM/YYYY
格式。为什么使用trunc?这使得索引的选择性大大降低,因此不太可能被使用。如果您在查询中检查时间是否在两个日期之间,那么在没有trunc的情况下也可以正常工作。@AlexPoole在解释计划中使用
select*/*+INDEX(TIM\u RECEPT)*/
,我会得到相同的结果
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'))