Sql Oracle索引时间戳
场景: 我有一个568801行的表,在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>
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'))