【问题标题】:Oracle plan difference with "in" and "between"Oracle 计划与“in”和“between”的区别
【发布时间】:2013-09-09 15:24:15
【问题描述】:

你能帮我完成这个我不明白的计划吗? 我正在运行一个非常简单的请求:

SELECT *
FROM  BOOKING.BOOKING_GRID BG
WHERE BG.hotel=128 and day between 8600 and 8602;

还有另一个版本:

SELECT *
FROM  BOOKING.BOOKING_GRID BG
WHERE BG.hotel=128 and day in (8600,8601,8602);

我不明白为什么“中间”版本使用 BOOKING_GRID_INDEX5 而“in”版本不使用?表现很不一样!是不是因为IOT索引不能进行“范围扫描”?

感谢您的帮助!


表索引为:

BOOKING BOOKING_GRIDPK  UNIQUE  VALID   IOT - TOP   N   NO      NO  HOTEL, DAY, BOOKINGSTATE    
BOOKING BOOKING_GRID_UNIQ   UNIQUE  VALID   NORMAL  N   NO      NO  HOTEL, DAY, BOOKING, VALIDITYSTART  
BOOKING BOOKING_GRID_INDEX5 NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKINGSTATUS, ISDAYUSE, DAY 
BOOKING BOOKING_GRID_INDEX7 NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, BOOKING, VALIDITYSTART   
BOOKING BOOKING_GRID_INDEX10    NONUNIQUE   VALID   NORMAL  N   NO      NO  HOTEL, ISDAYUSE, BOOKINGSTATUS, DAY 

这就是我得到的:

SQL> SELECT *
  2  FROM  BOOKING.BOOKING_GRID BG
  3  WHERE BG.hotel=128 and day between 8600 and 8602;

3584 ligne(s) sÚlectionnÚe(s).


Plan d'exÚcution
----------------------------------------------------------
Plan hash value: 1060169596

-----------------------------------------------------------------------------------------

| Id  | Operation         | Name                | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |                     |  6504 |   508K|   845   (5)| 00:00:11 |

|*  1 |  INDEX UNIQUE SCAN| BOOKING_GRIDPK      |  6504 |   508K|   845   (5)| 00:00:11 |

|*  2 |   INDEX SKIP SCAN | BOOKING_GRID_INDEX5 |   464 |       |   480   (7)| 00:00:06 |

-----------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("BG"."HOTEL"=128 AND "DAY">=8600 AND "DAY"<=8602)
   2 - access("BG"."HOTEL"=128 AND "DAY">=8600 AND "DAY"<=8602)
       filter("DAY">=8600 AND "DAY"<=8602)


Statistiques
----------------------------------------------------------
         58  recursive calls
          0  db block gets
       6961  consistent gets
          0  physical reads
          0  redo size
     200030  bytes sent via SQL*Net to client
       3142  bytes received via SQL*Net from client
        240  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       3584  rows processed




SQL> SELECT *
  2  FROM  BOOKING.BOOKING_GRID BG
  3  WHERE BG.hotel=128 and day in(8600,8601,8602);

3584 ligne(s) sÚlectionnÚe(s).


Plan d'exÚcution
----------------------------------------------------------
Plan hash value: 1233826949

------------------------------------------------------------------------------------

| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |                |  1869 |   146K|   681   (0)| 00:00:09 |

|   1 |  INLIST ITERATOR  |                |       |       |            |          |

|*  2 |   INDEX RANGE SCAN| BOOKING_GRIDPK |  1869 |   146K|    36   (0)| 00:00:01 |

------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("BG"."HOTEL"=128 AND ("DAY"=8600 OR "DAY"=8601 OR "DAY"=8602))


Statistiques
----------------------------------------------------------
         57  recursive calls
          0  db block gets
        687  consistent gets
          0  physical reads
          0  redo size
     200192  bytes sent via SQL*Net to client
       3142  bytes received via SQL*Net from client
        240  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       3584  rows processed

添加时间:2013 年 9 月 9 日

每个索引的聚类因子详细信息:

Table       Index            Cluster. factor     Table NRows
BOOKING_GRID    BOOKING_GRID_INDEX7  276 816 902     313 290 258   
BOOKING_GRID    BOOKING_GRID_UNIQ    131 055 933     313 290 258   
BOOKING_GRID    BOOKING_GRID_INDEX10     121 702 397     313 290 258   
BOOKING_GRID    BOOKING_GRIDPK       108 115 708     313 290 258   
BOOKING_GRID    BOOKING_GRID_INDEX5   24 238 404     313 290 258 

【问题讨论】:

    标签: oracle11g sql-execution-plan


    【解决方案1】:

    我会从这个开始:IN 处理一个离散列表(这里只有 3 个值),其中 BETWEEN 必须考虑连续范围。 (检查返回的预期行:IN 示例为 1869,BETWEEN 为 6504。)

    【讨论】:

    • 什么意思? INDEX RANGE SCAN(在请求计划中)是否考虑了一系列连续值?我不明白为什么应该有任何区别。 BETWEEN-request计划中使用的双索引也可以与错误的PHYSICAL GUESSES问题有关吗?
    • @RenaudBlue - 不,INDEX RANGE SCAN 正在考虑一系列索引条目,这些条目可能完全不连续,如 3、4、5、17、109 等。(请记住,它只存储值在表中。)在数学中考虑“连续” - 在 8600 和 8602 之间有无限数量的实数,而不是 3。
    • 是的,我看到了枚举值和连续范围值之间的区别。但是在这种情况下,天是离散的整数,并且上面有索引。所以我希望我可以在那里优化......我的第一个问题是我们在索引组织表中,所以当我可以使用主 IOT 索引 BOOKING_GRID_PK 时,为什么我要使用 BOOKING_GRID_INDEX5 和 SKIP SCAN!
    • @RenaudBlue - 抱歉,关于优化器,我找不到关于 IN 与 BETWEEN 的任何明确信息,但在我的测试中,BETWEEN 总是估计返回的行数更高(我正在测试使用 NUMBER(10))。至于SKIP SCAN,我同意它没有选择PK指数很奇怪;也许尝试一个提示,看看你是否可以强制它。如果这有帮助,可能值得检查表/索引上的统计信息。
    • 我已经添加了关于表 n 行和聚类因子的信息。看到IOTable的主索引有这么大的聚类因子,我感到非常惊讶。并且还可以看到辅助索引可以具有比主索引更低的聚集因子。你怎么看?
    猜你喜欢
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2020-06-03
    相关资源
    最近更新 更多