此查询的 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 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

查询优化 [Oracle]

一个棘手的删除查询的 Oracle 查询优化

Oracle 查询性能优化

需要帮助来优化 ORACLE SQL 查询 [关闭]

Oracle 优化——奇怪的执行计划左加入一个不相关的子查询

oracle 优化时间查询