記一次Oracle千萬級數據查詢與千萬級數據新增的調優過程

因爲業務需要,我要做一個後臺接口,用來處理一個月的生成訂單的處理。查詢的數據量維持在九百萬條數據左右。

我第一次是在dev環境跑的單元測試,沒有考慮到這麼大的數據量,sit造的數據量也不大,等到hotfix就懵逼了,一下查出了900多萬條,僅僅是查詢就耗費了很長時間,查詢之後還要進行insert,每次insert還要驗證數據是否重複。結果就是直接把做系統整癱瘓了。

這段sql不忍直視,而且更嚴重的是,我把查詢出來的結果都放到了list裏面,這就把JVM所有的內存都沾滿了,其他人的定時任務就沒法跑了。

優化:

1、SQL拆分優化:

開始的時候我用的是UNION ALL ,但是嘛,下面那個select函數查詢的數據量其實很小,所以可以將兩個sql分開。這樣可以節省一部分時間。

2、將not in改爲not exists

and not exists( select 1 from FEE_ORG_*** c where c.MY_ORDER_ID = a.my_order_id and start_date = to_number(@startDate) and end_date = to_number(@endDate))(後面這個將去掉,因爲在存儲的時候還要做一次校驗,這個not exists會拖慢整體速度。)

3、and  to_char(a.LATEST_STATUS_TIME,'yyyyMMdd') >= to_char(SYSDATE + ( 1 - @day)),將左邊的to_char去掉,轉換右邊的就可以了,因爲左邊的字段to_char會將查詢結果的每一條數據都進行轉換,而轉換右邊的只需要轉換一次就可以了。

4、去掉所有的to_number,只需要再傳入參數的時候進行初始化爲int型就可以了。

5、加索引,create index fee_order_**_01 on fee_order_**(start_date ,end_date,MY_ORDER_ID);

6、在distinct之前加一個/*+ leading(a) index(a idx_efsw_loan_**_01) */,因爲業務需要這幾個關聯的表必須進行join關聯,速度不可避免的會很慢。加了/*+ leading(a) index(a idx_efsw_loan***_01) */主要是爲了強制是efsw_loan***表作爲主表進行關聯查詢。經過以上優化,百萬級查詢只需要十幾秒;

7、sql優化之後,接下來就是程序的優化了,優化的思想就是分頁查詢,不能一次性的將所有的數據查出來放到list中, 我採用的是每次查5000,執行5000條,下面是代碼優化:

最後在dev環境進行了實驗,數據是20萬,每次執行的條數是5000條,耗時30秒 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章