公司服務器崩了,很多測試環境用不了,弄了一個生產庫還原到本地,調了下統計分析系統的一些存儲過程:
場景:首頁一進去就加載七個報表,而且是實時計算的。。。不光耗資源,還會鎖住ajax,串行一個個執行這七個存儲過程,導致其它的ajax執行不了(表現在點擊其它子菜單無響應,要等前面ajax用完了才會輪到后面)
1、固化數據、緩存什么的,先不考慮,還是按原樣先動態實時取首頁吧,接手過來的項目先不急着翻新,先看能否花半天一天優化。
2、按前幾天學的在控制器上設置Session的ReadOnly,刷新首頁發現死鎖。。。而且是每次必死鎖
3、檢查存儲過程,發現里面都有兩句UPDATE全庫的一個字段,如果是NULL則取另一個值。這個沒必要每次查詢都去全庫更新,會鎖表,也不可能存在這么多異常數據,這種數據修正的,放在每晚同步時處理就好了,去掉后不再死鎖。
4、並行后,速度反正不如原先串行的。。。串行的每個執行只要1~3秒(雖然也不短),但整體下來還好,一個個等它輪圈,二十秒左右也全部加載完了。但並行后,每個都要花掉10~20秒左右。。。翻了好幾倍
5、復制出來執行,一個個又恢復到1~3秒,懷疑是並發引起,又不好重現並發場景,就把SQL窗口縮小,屏幕上並排擺了7個,一個個快速切換到窗口用快捷鍵執行,這樣也重現出了速度慢的情況。
6、觀察存儲過程,有兩張大表(幾十萬),沒加索引。加完索引后,效果不明顯。
7、再觀察用到原表很少,幾乎都是先把原表數據SELECT * INTO至一個臨時表。有些過濾條件都過濾不了多少,幾乎相當於原表全進內存(臨時表)了
8、把SELECT * 改為只要用到的4個字段,效果不明顯
9、發現一個大表寫了兩次,而第二次的臨時表后面完全沒用到(Ctrl + F搜索),去掉后效果顯著,正常了。
10、初步懷疑是大表進內存太多了,剛好到一個臨界值,再加一張大表就會觸發tempdb和磁盤進行大量IO或頁查找之類(不懂底層原理。。。)。臨時表不是萬能葯,只是數據量少時用臨時表才有效,幾十萬的數據進臨時表有時適得其反。
11、臨時表和真實表的區別,如果體量差不多,臨時表沒有索引,沒法優化,還不如有索引的真實表。存儲過程是支持給臨時表加索引。
今天一開始也是這樣嘗試給臨時表加索引的,但索引只用一次,效率反而比不上不加。因為加索引也是要時間的,加完只執行一兩段就結束了,加索引所耗的時間還沒賺回來。
12、期間也懷疑了【參數嗅探】,即要在存儲過程里再定義個內部變量去接收傳進來的參數。試了無效,且存儲過程里面大量拼接字符串,這種拼字符串也是很影響分析器分析的。
性能優化,主要還是集中在數據庫這里。能差好幾倍,現在PC、服務器性能都不錯了,前端的JS解析,除非循環太大或是有超大table,不然完全感覺不出來。服務器的性能雖然也比較緊張,但並發量不大的話也看不出區別。就是數據庫一差能差很遠,隨時卡死卡崩喜聞樂見。