1. 程式人生 > >SQL優化實戰:臨時表+分批提交+按日結存

SQL優化實戰:臨時表+分批提交+按日結存

結存資料太慢怎麼辦?

(1)第1次優化

一開始,客戶經理說客戶,不想在多個查詢中看資料,想在一個表中看所有的資料,也就是說需要把原有的多個查詢的sql合併為一個,但是實際上合併後,每個月的原始資料量大概是100w條左右,然後進行計算,最後返回大概3w條左右,速度比較慢。


然後,客戶反饋,在查詢資料時非常慢,基本上查詢1個月的資料,需要5分鐘,於是對sql中涉及到的表,都更新了統計資訊,速度提高不少。

(2)第2次優化

之後,客戶說需要顯示結存的資料,於是修改sql,增加了表關聯,但是速度又慢了。


再之後,嘗試用了修改sql,但是效果都不理想。

最後想出的辦法是,新建結存表,新建儲存過程,然後把資料預先結存到表中。


通過一個儲存過程,來結存2015年全年的資料,每次結存一個月的資料。
在結存1、2、3月時,每個月在2分鐘左右,但從4月份開始,結存一個月資料10分鐘都不止。

一開始,由於結存時間過長,也無法判斷有多少資料已經結存進去,所以直接kill,但是rollback時間達到了20分鐘。

後來,通過 select * from tb with(nolock)查詢,大致能掌握已結存進去多少資料。

(3)第3次優化

接下來進行了幾種嘗試:
1、rebuild index,通過重建索引,來減少索引的碎片。
2、刪除日期欄位biz_date上的索引,減少需要維護的索引數量,加快insert的速度。
3、刪除聚集索引,同2。

4、先插入臨時表,再把臨時表的資料插入表中。

但是以上4種嘗試,基本上無效,通過:
select * from sys.sysprocesses where spid = xx

發現查詢資料的時候比較快,但是在insert時很慢,基本上都是PAGEIOLATCHEX等待,這個等待基本上說明是 由於磁碟的寫入等待,導致速度很慢。

那麼在磁碟寫入速度很慢的情況下,如何提高速度呢?

(4)第4次優化

嘗試了下面的2種方法:

1、先把1個月的資料存入臨時表,建立索引,然後每1w條資料提交1次。
2、把儲存過程修改為按日結存。
最後,這2種方法,都能在3分鐘以內,結存一個月的資料,且第1個方法最快,只需要2分鐘左右,但是第1個方法需要寫的程式碼比較多。


總結一下:
隨著表的資料越來越多,插入速度越來越慢,通過分批插入資料,然後提交,來提高速度。
這裡的關鍵是分批,每一批的大小,太大的話,雖然提交次數少了,但是對磁碟壓力太大,必然會有長時間等待。

如果太小,那麼提交次數太多,甚至每次插入資料的時間比每次提交所消耗的時間還小,而資料很多,這樣以計算,就會發現,消耗在提交上的時間,可能都查過了 插入資料的時間。