【发布时间】:2018-01-30 14:26:57
【问题描述】:
为什么这个从给定时间开始检索前 100 行的简单查询不使用索引?
SELECT *
FROM (SELECT *
FROM requests
WHERE client_time >= TO_TIMESTAMP('2017-07-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY client_time ASC, transaction_id ASC
)
WHERE rownum <= 100;
client_time 是TIMESTAMP WITH LOCAL TIME ZONE,transaction_id 是VARCHAR2(255 CHAR)。
我希望它使用的索引被定义为
CREATE UNIQUE INDEX idx_time_id REQUESTS (client_time, transaction_id);
查询执行需要大约 2 秒(我的系统中有 600 万行,生产中会更多)并产生以下计划:
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 110K| | 31237 (1)| 00:06:15 |
|* 1 | COUNT STOPKEY | | | | | | |
| 2 | VIEW | | 860K| 931M| | 31237 (1)| 00:06:15 |
|* 3 | SORT ORDER BY STOPKEY| | 860K| 65M| 86M| 31237 (1)| 00:06:15 |
|* 4 | TABLE ACCESS FULL | REQUESTS | 860K| 65M| | 15294 (1)| 00:03:04 |
----------------------------------------------------------------------------------------------------
谓词信息(由操作id标识):
1 - filter(ROWNUM<=100)
3 - filter(ROWNUM<=100)
4 - filter("CLIENT_TIME">=TIMESTAMP' 2017-07-01 10:00:00,000000000')
当我删除我的 ORDER BY 子句的第二部分时,实际上使用了这个索引并且查询在大约 1 毫秒内执行。
如果我得到this Use the index, Luke 的文章是正确的,我的查询不应该也使用这个索引吗?
更新:
删除我的二阶列后的计划如下:
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 65100 | 106 (0)| 00:00:02 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 102 | 66402 | 106 (0)| 00:00:02 |
| 3 | TABLE ACCESS BY INDEX ROWID| TRX_REQUESTS_LTZ | 102 | 8160 | 106 (0)| 00:00:02 |
|* 4 | INDEX RANGE SCAN | IDX_TIME_ID | | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
所以我相信 WHERE 子句不是这里的问题。此外,像这样重写 WHERE 后没有任何变化:
WHERE client_time >= TO_TIMESTAMP_TZ('2017-07-01 10:00:00 +10:00', 'YYYY-MM-DD HH24:MI:SS TZH:TZM')
【问题讨论】:
标签: sql indexing oracle11g oracle-xe