我有tableA
,它(列表)几乎被5个值平均分配。 tableA
包含1亿行,并且在customFunc(x)
上具有本地(分区)索引。以下查询使用所提到的索引执行RANGE SCAN
,并执行大约5到10秒钟,并返回500万。
select count(*) from tableA where customFunc(x)='abc';
不幸的是,当我尝试在特定分区上执行相同的查询时,它会进行全表扫描,并且要花很长时间。
select count(*) from tableA where customFunc(x)='abc' and partitioning_key='DT';
我完全不明白为什么会这样。.在第二种情况下,它不应该利用分区修剪吗?
编辑:添加提示/*+ index(tableA mentionedIndex) */
解决了此问题,但是我仍然不明白为什么默认情况下不使用它
编辑:XPLAN 1
Plan hash value: xxx
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 29335 (1)| 00:00:02 | | |
| 1 | SORT AGGREGATE | | 1 | 17 | | | | |
| 2 | PARTITION LIST ALL| | 5227K| 84M| 29335 (1)| 00:00:02 | 1 | 5 |
|* 3 | INDEX RANGE SCAN | CUSTOM_FUNC_INDEX | 5227K| 84M| 29335 (1)| 00:00:02 | 1 | 5 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access(customFunc(x)='abc')
XPLAN 2(带有分区键)
Plan hash value: yyy
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 679K (2)| 00:00:27 | | |
| 1 | SORT AGGREGATE | | 1 | 30 | | | | |
| 2 | PARTITION LIST SINGLE| | 4014K| 114M| 679K (2)| 00:00:27 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | tableA | 4014K| 114M| 679K (2)| 00:00:27 | 1 | 1 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(customFunc(x)='abc')
答案 0 :(得分:0)
在第二种情况下不应该利用分区修剪吗?
第二个查询确实应用分区修剪:这就是该步骤的含义:PARTITION LIST SINGLE
。问题是分区修剪意味着读取整个分区:在第二个计划中,步骤TABLE ACCESS FULL
意味着读取分区中的所有行,而不使用索引。因此,第二个查询正在评估分区中的每一行的customFunc(x)='abc'
。
使用分区键创建本地索引有什么意义?
区别在于,以分区键为前缀的本地索引将始终使用分区修剪,而当本地索引不具有分区键时,优化程序可以选择是否应用分区修剪。但是,如果要运行不使用分区键的查询,那么显然需要非前缀版本。
现在您应该感到困惑。给定分区键作为谓词,优化器应对指定的分区执行INDEX RANGE SCAN
。要弄清楚为什么不这样做,您需要付出更多的努力。您的统计信息可能过时,或者您需要收集直方图。它是基于函数的索引这一事实可能会使优化器感到困惑。如果您有访问权限,或有合作的DBA,则可以使用10053事件来深入了解。 Find out more。