【发布时间】:2016-10-23 15:51:11
【问题描述】:
我正在尝试按时间检索具有超过 100 万条记录的表中超过 100K 行的用户的最后 20 行。当用户有少量记录时,查询性能很好(以毫秒为单位)。但是对于大约 10K-100K 记录的用户,获取 20 条记录需要 2 多分钟。
这是查询:
select * from ( select * from TABLE1
where USER_ID= 41063660 and
COL1=0 and COL2 = 0
order by LAST_EVENT_DATE desc) where rownum <= 20 ;
(USER_ID、COL1、COL2、LAST_EVENT_DATE DESC)上有一个索引(I_LASTEVENTDT)
这里是解释计划:
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20 | 38960 | | 66959 (1)| 00:13:24 |
|* 1 | COUNT STOPKEY | | | | | | |
| 2 | VIEW | | 65500 | 121M| | 66959 (1)| 00:13:24 |
|* 3 | SORT ORDER BY STOPKEY | | 65500 | 96M| 102M| 66959 (1)| 00:13:24 |
| 4 | TABLE ACCESS BY INDEX ROWID| TABLE1 | 65500 | 96M| | 47280 (1)| 00:09:28 |
|* 5 | INDEX RANGE SCAN | I_LASTEVENTDT | 65500 | | | 309 (0)| 00:00:04 |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=20)
3 - filter(ROWNUM<=20)
5 - access("USER_ID"=41063660 AND "COL1"=0 AND
"COL2"=0)
我尝试按照http://use-the-index-luke.com/sql/sorting-grouping/indexed-order-by 上给出的示例进行操作
我也尝试在 (USER_ID, COL1, COL2) 和 (LAST_EVENT_DT DESC) 上创建单独的索引,并尝试在 (USER_ID,LAST_EVENT_DT DESC) 上创建索引。尽管对于后一个索引它摆脱了排序顺序,但两者的性能都更差。
如何从这个查询中获得更好的性能?
提前致谢。
【问题讨论】:
-
解释计划说,65K 行的查询只用了 15 秒(我希望我没有误读)。你怎么说需要2分钟?查询前后是否做更多处理?
-
计划显示的是 13 分钟,而不是 15 秒,并且只是一个估计值。当我从我的应用程序运行它时,它需要 2 分钟以上,具体取决于获取的行数。
-
糟糕。感谢您澄清这一点。仅出于调查目的,您是否尝试在查询中添加
FIRST_ROWS提示?它会改变解释计划吗? -
没有尝试过..但据我所知,即使我将提示放在查询中,CBO 也可以随意忽略提示
-
也许可以使用本页上的最后一个示例作为指导尝试一下? docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm
标签: oracle oracle11g sql-order-by top-n