我正在使用一个用作过滤器的索引列,方法是将它放在两个文字值之间。(该列位于索引的第二个位置,实际上使执行速度变慢;我稍后会处理)。
令我困惑的是,Oracle(11.2.0.3.0)根据提供给 to_date 的值和格式字符串的格式使用或忽略所述索引:
这忽略了索引:
SQL> SELECT *
2 FROM gprs_history_import gh
3 WHERE start_call_date_time BETWEEN
4 to_date('20140610 000000','yyyymmdd hh24miss') AND
5 to_date('20140610 235959','yyyymmdd hh24miss')
6 /
Execution Plan
----------------------------------------------------------
Plan hash value: 990804809
--------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 350 | 219K| 242K (1)| 00:56:42 | | |
| 1 | PARTITION RANGE SINGLE| | 350 | 219K| 242K (1)| 00:56:42 | 74 | 74 |
| 2 | PARTITION LIST ALL | | 350 | 219K| 242K (1)| 00:56:42 | 1 | 3 |
|* 3 | TABLE ACCESS FULL | GPRS_HISTORY_IMPORT | 350 | 219K| 242K (1)| 00:56:42 | 220 | 222 |
--------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("START_CALL_DATE_TIME"<=TO_DATE(' 2014-06-10 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
这个确实使用了索引(注意第 4 行中日期部分之后的空格):
SQL> SELECT *
2 FROM gprs_history_import gh
3 WHERE start_call_date_time BETWEEN
4 to_date('20140610 ','yyyymmdd ') AND
5 to_date('20140610 235959','yyyymmdd hh24miss')
6 /
Execution Plan
----------------------------------------------------------
Plan hash value: 464458373
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 350 | 219K| 2795K (1)| 10:52:15 | | |
|* 1 | FILTER | | | | | | | |
| 2 | PARTITION RANGE ITERATOR | | 350 | 219K| 2795K (1)| 10:52:15 | KEY | 74 |
| 3 | PARTITION LIST ALL | | 350 | 219K| 2795K (1)| 10:52:15 | 1 | 3 |
| 4 | TABLE ACCESS BY LOCAL INDEX ROWID| GPRS_HISTORY_IMPORT | 350 | 219K| 2795K (1)| 10:52:15 | KEY | 222 |
|* 5 | INDEX SKIP SCAN | GPRS_HISTORY_IMPORT_IDX1 | 1 | | 2795K (1)| 10:52:15 | KEY | 222 |
---------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_DATE('20140610 ','yyyymmdd ')<=TO_DATE(' 2014-06-10 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
5 - access("START_CALL_DATE_TIME">=TO_DATE('20140610 ','yyyymmdd ') AND "START_CALL_DATE_TIME"<=TO_DATE(' 2014-06-10
23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
filter("START_CALL_DATE_TIME">=TO_DATE('20140610 ','yyyymmdd ') AND "START_CALL_DATE_TIME"<=TO_DATE(' 2014-06-10
23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
((1)中的过滤器看起来有点傻,好像Oracle没看懂表达式)
同样,这个没有(我删除了尾随空格):
SQL> SELECT *
2 FROM gprs_history_import gh
3 WHERE start_call_date_time BETWEEN
4 to_date('20140610','yyyymmdd') AND
5 to_date('20140610 235959','yyyymmdd hh24miss')
6 /
Execution Plan
----------------------------------------------------------
Plan hash value: 990804809
--------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 350 | 219K| 242K (1)| 00:56:42 | | |
| 1 | PARTITION RANGE SINGLE| | 350 | 219K| 242K (1)| 00:56:42 | 74 | 74 |
| 2 | PARTITION LIST ALL | | 350 | 219K| 242K (1)| 00:56:42 | 1 | 3 |
|* 3 | TABLE ACCESS FULL | GPRS_HISTORY_IMPORT | 350 | 219K| 242K (1)| 00:56:42 | 220 | 222 |
--------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("START_CALL_DATE_TIME"<=TO_DATE(' 2014-06-10 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))
在空格周围加上引号会阻止索引被使用。
是什么赋予了?