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_COUNT 与 FTS
和 INDEX ACCES
之间的选择高度相关。
类似适用于System Statistics设置。
最后备注
要访问大型 table 的非平凡部分(比如 100 天中的 50 个)不需要 INDEX ACCESS
的用例。检查 分区功能 ,其中 (range partitioning)
专为此类访问而设计。
场景:
我有一个包含 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_COUNT 与 FTS
和 INDEX ACCES
之间的选择高度相关。
类似适用于System Statistics设置。
最后备注
要访问大型 table 的非平凡部分(比如 100 天中的 50 个)不需要 INDEX ACCESS
的用例。检查 分区功能 ,其中 (range partitioning)
专为此类访问而设计。