使用 Order by 與 rownum SQL 優化案例一則

這是某客戶AWR報告中的一個TOP SQL,執行時間8.8小時(也有執行12.7小時報錯退出的狀況)sql

SELECT *性能優化

FROM 微信

(oracle

 SELECT rownum num ,t.*性能

 FROM TI_BI_CAMPN_USERORDER_TEMP t測試

 WHERE oper_type = '0' OR oper_type = '2' OR優化

  (oper_type = '1' AND end_date <= add_months(trunc(sysdate, 'mm'), 1))spa

 ORDER BY oper_time ASC.net

 ) c排序

WHERE c.num <= : 1;


表記錄數280M,返回其中符合條件並按oper_time排序的500條記錄。


看到上面sql monitor顯示的執行計劃,可能有人會生出疑問:

返回了表的大部分記錄,爲何不作全表掃描,而是使用了比較差的索引掃描?


答案是:

由於修改了索引相關的兩個系統參數,把索引的COST大大的下降了,讓優化器認爲走索引老是比全表掃描要好:

optimizer_index_caching = 95(默認值0)

optimizer_index_cost_adj = 3(默認值100)


這個SQL如何優化呢?


根據SQL monitor顯示的信息及表的實際記錄數,咱們能夠經過建立oper_time字段上的索引來優化:

create index idx_name on TI_BI_CAMPN_USERORDER_TEMP(oper_time);

預計建立索引後,該SQL的執行時間應該在1~2秒左右


小結:

    order by 與 rownum 搭配使用時,能夠建立謂詞字段與order by字段上的聯合索引(本例不可,由於有or和不對稱的謂詞條件);或者在大部分數據都符合條件的狀況下,建立order by字段上的索引(本例),避免大結果集的排序。

    系統默認參數通常不建議修改(內存參數、bug除外),由於不少性能測試是在默認參數條件下完成。


其餘狀況:


若是這個SQL執行頻率低,也能夠選擇不建立索引,使用並行加全表掃描來提升響應速度,使用下面的hint:

SELECT *

FROM 

(

 SELECT /*+ full(t) parallel(4) */rownum num ,t.*

 FROM TI_BI_CAMPN_USERORDER_TEMP t

 WHERE oper_type = '0' OR oper_type = '2' OR

        (oper_type = '1' AND end_date <= add_months(trunc(sysdate, 'mm'), 1))

 ORDER BY oper_time ASC

 ) c

WHERE c.num <= : 1;


若是索引那兩個系統參數是默認值,其中的full hint是能夠去掉的。


當前使用的並行度是4,具體的並行度能夠根據實際須要適當增減。

注意:11g的並行寫法已經不要求加表名或別名。10g中加表名或別名的寫法繁瑣並且容易遺漏,拋棄了吧!




各位網友若是有什麼意見、建議、問題均可以與老虎劉溝通,能夠直接在公衆號發信息,或者發郵件到sql_tigerliu@126.com


老虎劉的文章都是原創,歡迎你們轉發。


本文分享自微信公衆號 - 老虎劉談oracle性能優化(sql_tigerliu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索