sql - Oracle 索引时间戳
问题描述
设想:
我有一个包含 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'))
对这个问题有任何想法吗?
解决方案
Oracle 优化器不使用索引这一事实并不是问题。当访问所消耗的资源(在大多数情况下是经过的时间) FULL TABLE SCAN
高于使用的替代执行计划INDEX ACCESS
(您没有明确说明)时,这是一个问题。
从优化器的角度来看,两个执行计划都很好,并且导致的时间大致相同。
因此,如果这些查询的体验不同,并且实际经过的时间与估计 (01:45) 有很大差异,您(或您的 DBA)应该采取以下步骤:
1)验证表的优化器统计信息
陈旧的统计数据可能会欺骗优化器。尤其是在您在小表上收集统计信息并插入大量记录的情况下。
2) 验证优化器参数和系统统计信息
一些参数特别是DB_FILE_MULTIBLOCK_READ_COUNTFTS
与和之间的选择高度相关INDEX ACCES
。
类似对系统统计设置有效。
最后的评论
要访问大表的重要部分(比如 100 天中的 50 个),不需要INDEX ACCESS
. 检查分区功能,它(范围分区)是为这种访问而设计的。
推荐阅读
- pandas - 熊猫识别是否有任何元素在一行中
- xamarin.forms - 为 Xamarin TableView 中的每个 EntryCell 设置相同的标签宽度
- python - 为什么迭代行会删除 csv.reader 和 csv.DictReader 中的数据?
- c# - 如何模拟 ActivityContext 类
- julia - 在 JuMP/Gurobi 中添加 OR 约束
- ios - 如何在 popViewController 之后从第二个 ViewController 执行功能?
- html - 如何在 HTML 中单击按钮时更改 iframe 源?
- r - 无法读取由 R 4.0.2 编写的工作区版本 3;需要 R 3.5.0 或更新版本
- sql - 排序依据——不同标准的不同顺序
- vb.net - 如何删除进程中当前正在使用的图像