Oracle 11g - top N order by 很慢

标签 oracle oracle11g sql-order-by top-n

我正在尝试按时间为拥有超过 100 万条记录的表中超过 100K 行的用户检索最后 20 行。当用户有少量记录时,查询性能很好(以毫秒为单位)。但是对于拥有大约 10K-100K 记录的用户,需要 2 分钟以上才能获取 20 条记录。

这是查询:

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) 上创建索引。尽管对于后一个索引,它摆脱了排序顺序,但两者的性能都更差。

如何从该查询中获得更好的性能?

提前致谢。

最佳答案

首先尝试这样的事情:

SELECT *
FROM 
   (SELECT *, ROW_NUMBER() OVER (ORDER BY last_event_date desc) R
    FROM table1
    WHERE user_id = 41063660
    AND col1 = 0
    AND col2 = 0)
WHERE R <= 20;

如果这证明速度不快,请尝试:

SELECT *
FROM table1,
    ( SELECT last_event_date, ROW_NUMBER() OVER (ORDER BY last_event_date desc) R
    FROM table1
    WHERE user_id = 41063660
    AND col1 = 0
    AND col2 = 0 ) sub
WHERE table1.user_id = 41063660
AND table1.col1 = 0
AND table1.col2 = 0
AND sub.R = 20
AND table1.last_event_date >= sub.last_event_date
AND ROWNUM <= 20;

可能有一种更直接的编写方式 - 我没有可供试用的 Oracle 实例。

另一种方法是实现一个 SQL 函数,仅在给定特定键的情况下获取第 20(或第 N)行的日期。然后以类似于我的第二个示例但没有子查询的样式调用该 SQL 函数。

关于Oracle 11g - top N order by 很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37955581/

相关文章:

sql - Oracle SQL CASE WHEN ORA-00932 : inconsistent datatypes: expected CHAR got NUMBER 00932. 00000 - "inconsistent datatypes: expected %s got %s"

sql - 如何使用 Groovy 从 Oracle 获取光标?

oracle - ssl_error_rx_record_too_long

mysql - 对有序子查询中的第一个结果进行分组

Mysql查询按两个整数列排序

java - WSJDBCConnection 不包装 oracle.jdbc.OracleConnection 类型的对象

sql - rowid 插入 Oracle 后可以立即失效吗?

oracle - 想在 Oracle 中生成如下的 o/p

python - 如何从 django 模型 DateTimeField 获取本地日期时间?

mysql - 从 mysql order by IN 子句获取结果