2017-04-24 114 views
0

我有一個表現不佳的SQL,它使用ROWNUMBER函數進行分頁。頁面大小早期設置爲5000,但已更改爲100.在較低環境下的測試中,響應時間從此變更後的7秒降至1秒以下。SQL ROWNUMBER效率

但是,由於查詢沒有太多過濾器,因此例如,如果謂詞中的LAST_UPD_DT設置爲今天,則可能會發生全表掃描。

所以在這種情況下,將ROWNUMBER設置爲低得多的幫助還是沒什麼區別?

生產中有大約250萬條記錄,測試中大約有5千條記錄,我看到響應從7秒降到1秒以下。

該查詢使用與謂詞具有相同列的索引。 ORIG_TIME列目前沒有索引,但會被添加。數據庫是DB2。

下面是查詢的修剪版本,它保留了問題的基本本質。

SELECT * 
    FROM 
     ( 
     SELECT ROWNUMBER () OVER ( 
     ORDER BY MEMBERS.ORIG_TIME ASC), 
       MEMBERS.APP_ID, 
       MEMBERS.NAME 
     FROM MEMBERS 
     WHERE 
      MEMBERS.LAST_UPD_DT <= ? AND 
      (MEMBERS.STAT_CD = 'S' OR MEMBERS.CURR_STAT = 'D') 
     ORDER BY MEMBERS.ORIG_TIME ASC 
    ) 
     AS TEMP_ 
    WHERE ROWNUMBER_ <= 100 --used to be 5000 

任何想法或援助將不勝感激。謝謝。

+0

是'last_upd_dt'場索引?如果是這樣,爲什麼你認爲會有一個表掃描? –

+0

@DanBracuk是的。也許我錯了,但如果查詢從表中返回大量記錄,那麼優化器會發現執行表掃描而不是索引查找效率更高,然後從表中讀取數據? – scifi2008

+0

在子查詢中'ORDER BY MEMBERS.ORIG_TIME ASC'是毫無意義的;如果您需要該訂單,請將其置於外部選擇之後。 – mustaccio

回答

0

加入您的索引和糾正您的查詢喜歡它:

SELECT * 
FROM 
    ( 
    SELECT ROWNUMBER () OVER (ORDER BY MEMBERS.ORIG_TIME ASC) as RANG, 
      MEMBERS.APP_ID, MEMBERS.NAME 
    FROM MEMBERS 
    WHERE 
    MEMBERS.LAST_UPD_DT <= ? AND (MEMBERS.STAT_CD = 'S' OR MEMBERS.CURR_STAT = 'D') 
) 
    AS TEMP 
WHERE RANG between 1 AND 5000 -- Modify here your range 
order by RANG