Oracle 根据 to_date(文字) 格式使用或忽略索引列
使用索引列作为过滤器并将其放置在“两个文字之间”。 (该列位于索引的第二个位置,这实际上使执行速度变慢;我稍后会讨论)。让我困惑的是,Oracle (11.2.0.3.0) 根据提供给 to_date 的值的格式和格式字符串来使用或忽略指定索引:
这会忽略索引:
- SQL> SELECT *
- 2 FROM gprs_history_import gh
- 3 其中 start_call_date_time 之间
- 4 to_date('20140610 000000','yyyymmdd hh24miss') AND
- 5 to_date('2 0140610 235959','yy yymmdd hh24小姐')
- 6 /
- 实施计划
- --------------------- ------------ -- -- -----------------
- 计划哈希值:990804809
- ------------------------------------------ ----- --- ------------------------------------------------- ----------
- |身份 |运营|名称 |行|字节 |成本(% CPU)|时间 |开始|停止 |
- ---------- -------------------------------- -- - ------------ ------------------------------- ------ - ---------
- | 0 |选择语句 | | 350 | 350 219K| 242K (1)| 00:56:42 | 00:56:42 | |
- | 1 |仅分区范围| 42 | 42 74 | 74 74 |
- | 2 |分区列表全部| | 350 | 350 219K| 242K (1)| 00:56:42 | 00:56:42 1 | 3 |
- |* 3 | | 219K| 242K (1)| 00:56:42 | 00:56:42 220 | 220 222 |
- ---------------------------- ------------- -- ---- --------------------------- ------------- ------ ---- ----------
- 谓词信息(通过操作ID标识):
- ----------------------------- -
- 3 - 过滤器("START_CALL_DATE_TIME" 从 gprs_history_import gh
- 3 中选择 *
- 2,其中 start_call_date_time 之间
- 4 to_date('20140610 ','yyyymmdd ') AND
- 5 to_date('20140610 235959',' yyyymmdd hh24miss')
- 6 /
- 执行计划
- --------------- - ----- -------------- -------------------
- 计划哈希值:464458373
- ------------------------------------------ ----- --- ------------------------------------------------ ---------- --- -------------
- |身份 |运营|名称 |行|字节 |成本(% CPU)|时间 |开始|停止 |
- -------------------------------------------------------- --- ------------------------------------------ -------- ----------------------------
- | 0 |选择语句 | | 350 | 350 219K | 219K 2795K (1)| 10:52:15 | 10:52:15 | |
- |* 1 |过滤器| | | | | | | |
- | 2 |分区范围迭代器 | 10:52:15 | 10:52:15关键| 74 |
- | 3 |分区列表全部| | 350 | 350 219K| 2795K (1)| 10:52:15 | 10:52:15 1 | 3 |
- | 4 |指数RIDEID| GPRS_HISTORY_IMPORT | GPRS_HISTORY_IMPORT | 350 | 350 219K| 2795K (1)| 10:52:15 | 10:52:15关键| 222 |
- |* 5 |索引跳过扫描 | GPRS_HISTORY_IMPORT_IDX1 | 1 | | 2795K (1)| 10:52:15 | 10:52:15关键| 222 |
- ------------------------------------------------------------ ------------------------------------------ -------- ---------------------------
- 谓词信息(通过操作ID标识):
- -------------------------------------------- - --- -----------
- 1 - 过滤器(TO_DATE('20140610','yyyymmdd ')=TO_DATE('20140610','yyyymmdd ') AND "START_CALL_DATE_TIME"=TO_DATE('20140610','syyyy-mm-dd hh24 : mi:ss' ))
((1) 中的过滤器看起来有点奇怪,就像 Oracle 不理解这个表达式一样)
这也不适用于这个(我删除了尾随空格):
- SQL > 选择 *
- 2 来自 gprs_history_import gh
- 3 其中 start_call_date_time 之间
- 4 to_date('20140610','yyyymmdd') 和
- 5 to_date('20140610 235959','syyyy-mm-dd hh24:mi:s ) )
在空格两边加上引号不包括索引的使用。
什么给出了?
解决方法
好的 - 我会尝试一下,主要是从可用信息中减去:为什么 Oracle 选择不同的执行计划?
在您的第二个查询中,似乎存在不寻常的日期格式,优化器不知道结果日期的值是什么。您将看到过滤谓词:
1 - filter(TO_DATE('20140610 ′,'yyyymmdd') 全表扫描不一定是需要一个糟糕的计划...使用索引并不总是更快!
> 查询计划中的成本永远不会与实际执行时间或性能直接相关 - 它是一个内部指标,用于比较同一查询的不同计划(因此您无法比较不同查询的成本,例如查询 1、2 和3)
基本上,如果从表中返回大量行,在许多情况下执行不带索引访问的全表扫描会快得多,特别是在某些分区上执行时! – 表扫描仅访问与日期范围匹配的相关性 – 因此仅针对相关日期并返回该分区其中的所有行。这比查询每行的索引,然后通过索引访问检索行要快得多...尝试解析查询 - 分区上的全表扫描速度应该快 3 倍,并且 IO 少得多。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。