当前位置: 首页 > 知识库问答 >
问题:

甲骨文11g-排名前N的订单速度较慢

文建业
2023-03-14

我正在尝试为一个记录超过100万条的表中有超过10万行的用户按时间检索最后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 ;

在(用户ID、COL1、COL2、上次事件日期描述)上有一个索引(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)上创建索引。尽管后一个索引取消了排序顺序,但两者的性能都较差。

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

提前谢谢。

共有2个答案

戚侯林
2023-03-14

我认为您应该寻找索引快速全扫描,而不是整行排序。此外,我还试图实现少量记录(20条),并将它们再次连接到主表。

with Dates as (
    select /*+ Materialize */ LAST_EVENT_DATE 
       from ( select LAST_EVENT_DATE 
                      from TABLE1                                                                                                              
                     where USER_ID= 41063660  
                        and COL1=0 
                        and COL2 = 0
                     order by LAST_EVENT_DATE desc) 
       where rownum <= 20 )
select t2.* 
  from (
    select t1.*
      from TABLE1 t1 join Dates on t1.LAST_EVENT_DATE >= Dates.LAST_EVENT_DATE 
                               and t1.USER_ID= 41063660  
                               and t1.COL1=0 
                               and t1.COL2 = 0
    order by t1.LAST_EVENT_DATE desc) as t2
where rownum <= 20;
尹超
2023-03-14

首先,尝试以下方法:

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 forms,遇到了一个问题。我在表单中有两个具有相同字段的多个记录块。 我查询一个块的数据,它被填充。 哪里有一种方法可以将所有行从填充的块复制到“复制”块?

  • 问题内容: 在OracleDoc中没有表达式背后的例子,所以我尝试使用Java语法,这应该在查询后得到任何数字 但是什么也没显示! 问题答案: 出于争论的考虑,REGEXP_SUBSTR也可以工作:

  • Support for the Oracle database. The following table summarizes current support levels for database release versions. 支持的Oracle版本 The following dialect/DBAPI options are available. Please refer to ind

  • 问题内容: 我有一个表(日期,有效负载),其中包含约10年的数据,我想基于14天(2周)和90天(12周)的间隔计算移动平均值(MA),以显示有效负载的趋势 我已经写了这个查询,但是它得到了错误的值 实际上我知道是什么,但我不了解Oracle的工作原理! 我可以在Excel中进行计算,但是我需要在数据库级别执行此操作,能否请您告诉我如何执行此操作? 问题答案: 我不明白使用的目的是什么?根据文档,

  • 我需要一个特定的业务场景来设置一个实体(不是PK)上的字段,一个序列中的数字(序列必须是最小值和最大值之间的数字) 我这样定义序列: 在Java代码中,我从序列中检索数字,如下所示: 我的问题是: 如果我在一个事务中调用这个“中选择mySequence.nextval”,同时在另一个事务中调用相同的方法(并行请求),那么确定序列返回的值是不同的吗? 不可能从第一个事务中读取未提交的值吗? 因为假设

  • 问题内容: 我有一个名为的约束。我如何找到该约束是什么?有没有办法查询所有约束? 问题答案: 像所有数据字典视图一样,如果您只想检查当前架构,则为USER_CONSTRAINTS视图,对于管理用户则为DBA_CONSTRAINTS视图。 约束名称的构造指示系统生成的约束名称。例如,如果我们在表声明中指定NOT NULL。或者实际上是主键或唯一键。例如: 检查,主要。 通常,给关系约束一个明确的名称