2017-05-25 65 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是正確的,只需要照顧正確的索引設置 –