2017-05-25 121 views
0

我在数据库表中有百万条记录,其中包含帐户号,地址和更多列。我想用desc命令排序100行,我用rownum来做这件事,但查询需要很长时间才能执行,因为它先扫描整个表,然后按照排序顺序进行排序,然后应用rownum。SQL调优,长时间运行的查询+ rownum

什么是最小化查询执行时间的解决方案?

例如:

select * 
from 
    (select 
     acc_no, address 
    from 
     customer 
    order by 
     acc_no desc) 
where 
    ROWNUM <= 100; 
+0

您是否在客户表中定义了索引? – Sumit

+0

由于Sumit说你应该有一个索引,我认为acc_no是唯一的?如果它不是您的主键,那么至少应该在索引 – MarkD

+1

中涵盖哪些RDBMS是用于此目的的?请添加一个标签来指定您是使用'mysql','postgresql','sql-server','oracle'还是'db2' - 或者其他的东西。 –

回答

2

从以往的经验,我发现,TOP最适合这个场景。

而且你应该总是选择你只需要列并避免使用所有的卡(*)

SELECT TOP 100 [acc_no], [address] FROM [customer] ORDER BY [acc_no] DESC 

约TOP,LIMIT甚至ROWNUM有用的资源。

0

确保您在ACC_NO列使用索引。

  1. 如果您在acc_no上已经存在索引,请通过验证查询执行计划来检查在查询执行过程中是否使用了该索引。

要创建如果不存在一个新的索引,使用下面的查询:

Create index idx1 on customer(acc_no); -- If acc_no is not unique 
Create unique index idx1 on customer(acc_no); -- If acc_no is unique. Note: Unique index is faster. 
  • 如果解释计划输出看到“全表扫描”,那么它是优化器不使用索引的情况。
  • 有提示先尝试:

    select /*+ index(idx1) */ * from 
    (select 
        acc_no, address 
    from 
        customer 
    order by 
        acc_no desc) 
    where 
    ROWNUM <= 100; 
    
  • 如果有提示上面返回的结果快速查询,那么你需要检查为什么优化是故意忽略索引。一个可能的原因是过时的统计数据。刷新统计信息。
  • 希望这会有所帮助。

    +0

    谢谢@Shinchan – Kamal

    0

    请考虑在内部查询/内嵌视图中获取顶级帐户号码,以便仅对这100个客户记录执行联合。否则,你可能会在百万行上执行所有连接,然后对百万个+结果进行排序以获得前100个。这样的事情可能会起作用。

    select ..... 
        from customer 
        where customer.acc_no in (select acc_no from 
             (select inner_cust.acc_no 
             from customer inner_cust 
             order by inner_cust.acc_no desc 
             ) 
            where rownum <= 100) 
         and ... 
    

    或者,如果你正在使用12C可以使用FETCH FIRST 100 ROWS ONLY

    select ..... 
        from customer 
        where customer.acc_no in (select inner_cust.acc_no 
               from customer inner_cust 
               order by inner_cust.acc_no desc 
               fetch first 100 rows only 
              ) 
         and ... 
    
    0

    这会给在100ms内的结果,但要确保则列ACC_NO指数。在ACC_NO +其他列上也可以有组合索引,但ACC_NO必须位于索引的第一个位置。您必须在执行计划中看到“范围扫描”。不是“全表扫描”,而不是“跳过扫描”。你可能会看到执行计划中的嵌套循环(这将从表中获取ADDRESSes)。通过为ACC_NO,ADDRESS创建组合索引(按此顺序),可以进一步提高速度。在这种情况下,Oracle引擎根本不必读取表,因为所有信息都包含在索引中。你可以在执行计划中比较它。

    select top 100 acc_no, address 
        from customer 
        order by acc_no desc 
    
    +0

    在oracle数据库中“顶”工作 – Kamal

    +0

    我不确定,在这种情况下你的SQL是正确的,只需要照顾正确的索引设置 –