此查询的 Oracle 查询优化
Posted
技术标签:
【中文标题】此查询的 Oracle 查询优化【英文标题】:Oracle Query optimization for this query 【发布时间】:2013-06-06 13:06:21 【问题描述】:请建议如何改进以下查询/索引以获得更快的结果。
查询
SELECT Tab1.pk, Tab1.c_RetryCount, Tab1.c_TimeCreated
FROM Table1 Tab1
WHERE ( ( Tab1.c_node = :1
OR Tab1.c_node IS NULL )
AND ( ( Tab1.c_RetryCount < :2
AND Tab1.c_TimeUpdated < :3 )
OR Tab1.c_RetryCount < :4 )
AND Tab1.c_SentStatus = :5 )
AND ( Tab1.c_Active = 1 )
AND ( Tab1.c_DelFlag = 0 )
AND ( Tab1.c_Shard = :6 )
ORDER BY Tab1.c_RetryCount ASC, Tab1.c_TimeCreated ASC
计划哈希值:2132878353
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 4 (100)| |
| 1 | SORT ORDER BY | | 43 | 2279 | 4 (25)| 00:00:01 |
| 2 | CONCATENATION | | | | | |
|* 3 | TABLE ACCESS BY INDEX ROWID| Table1 | 1 | 53 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | I_VOY52S_H881K4 | 1 | | 1 (0)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID| Table1 | 42 | 2226 | 2 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | I_VOY52S_H881K4 | 2 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
谓词信息(由操作id标识):
3 - filter(("Tab1"."c_DelFlag"=0 AND "Tab1"."c_ACTIVE"=1))
4 - access("Tab1"."c_Shard"=:6 AND "Tab1"."c_node" IS NULL
AND "Tab1"."c_SENTSTATUS"=:5)
filter(("Tab1"."c_SENTSTATUS"=:5 AND ("Tab1"."c_RETRYCOUNT"<:4 OR
("Tab1"."c_TIMEUPDATED"<:3 AND "Tab1"."c_RETRYCOUNT"<:2))))
5 - filter(("Tab1"."c_DelFlag"=0 AND "Tab1"."c_ACTIVE"=1))
6 - access("Tab1"."c_Shard"=:6 AND "Tab1"."c_node"=:1 AND
"Tab1"."c_SENTSTATUS"=:5)
filter(("Tab1"."c_SENTSTATUS"=:5 AND ("Tab1"."c_RETRYCOUNT"<:4 OR
("Tab1"."c_TIMEUPDATED"<:3 AND "Tab1"."c_RETRYCOUNT"<:2)) AND
LNNVL("Tab1"."c_node" IS NULL)))
表 Table1 索引:
I_VOY52S_19HS9Y5 (c_SENTSTATUS, c_ACTIVE, c_DelFlag)
I_VOY52S_1CPSX8O (c_node)
I_VOY52S_H881K4 (c_Shard, c_node, c_RETRYCOUNT, c_TIMEUPDATED, c_SENTSTATUS)
P_VOY52S_142KZ99 (pk)
【问题讨论】:
目前查询性能怎么样,你的目标是什么性能? 表中有多少条记录?它是否以任何方式分区?它主要用于读取还是用于 DML 操作?另外你可以给 c_node 添加默认值吗? 【参考方案1】:除了 c_Shard 之外,其他两个应用于每一行的单值过滤器使用 c_Active、c_DelFlag。因此,将这些添加到 I_VOY52S_H881K4 索引将提高这一查询的性能是一个很好的猜测。
或者,一个新的索引:
I_VOY52S_XXXXX (c_Shard, c_Active, c_DelFlag,
c_node, c_RETRYCOUNT, c_TIMEUPDATED, c_SENTSTATUS)
您甚至可以在接近尾声时加入 pk 和 c_timeCreated 以保持查询仅索引。
当然,当考虑其他查询或数据量时,创建这样的新索引可能完全不切实际;但是,由于您没有提到这一点,我假设拥有另一个非常适合这个查询的索引的成本为零。
所以,你会得到:
I_VOY52S_XXXXX (c_Shard, c_Active, c_DelFlag,
c_node, c_RETRYCOUNT, c_TIMEUPDATED, c_SENTSTATUS,
c_timecreated, pk)
【讨论】:
以上是关于此查询的 Oracle 查询优化的主要内容,如果未能解决你的问题,请参考以下文章