MIS性能优化常见问题与方案(辅助项目组性能优化的总结贴)
最近幫忙公司的幾個項目組進行了不同方面的性能優化,發現幾個項目都出現了一些共性的問題。這里寫一篇文章,總結一下這幾類問題,以及其對應的解決方案。方便其它項目組參考。
?
常見問題一:打開頁面非常慢,有的項目打開一個頁面竟然要 20 多秒。
優化步驟:
如果該請求是 JS 文件,則考慮使用壓縮版本(例如正在使用的 EXTJS,應該使用 ext-all.js 1.9M,而不是 ext-all-debug.js 4.5M)。
靜態資源要盡量啟用緩存。
每一個請求到達服務端后,都會做一系列的操作,例如:初始化當前用戶、角色、權限、當前模塊、業務邏輯、日志等。
對于前四個操作,往往是所有頁面都需要初始化的,那么我們需要使用 Session 或 Cache 等技術來優化,以防止每次請求都重新訪問數據庫。
對于業務邏輯、日志等,我們主要解決的是《ORM 中的 N+1 問題》、優化掉多余的數據庫訪問(需要記住,每一次數據庫訪問,其實都是一次遠程訪問)。
?
常見問題二:單條 SQL 語句執行較慢
在數據量較大的情況下,一些 SQL 語句執行得非常慢。
優化步驟:
http://www.cnblogs.com/leiOOlei/archive/2012/06/08/2541306.html
http://blog.csdn.net/hijiankang/article/details/9173877
是否真的需要為用戶提供一個查看幾十萬頁的數據的頁面?這樣的數據對于用戶來說,往往是沒用的。我們應該在功能模塊方面重新設計?
?
例如,下面這個 SQL,在壓力測試 1000 萬行數據時,已經需要 8 秒左右:
SELECT * FROM (SELECT T.*, ROWNUM RNFROM ( SELECT * FROM "T_PRIMITIVEDETAIL" "T0" WHERE "T0"."ORDERGOODSDATE" >= :p0 AND "T0"."ORDERGOODSDATE" <= :p1 AND "T0"."CORPORATION" = :p2 AND "T0"."DBI_ISPHANTOM" = :p3 ORDER BY "T0"."ID" ASC) TWHERE ROWNUM <= 5000010 ) WHERE RN >= 5000000 --Parameters:2016/5/1 0:00:00,2016/5/31 23:59:59,"惠州酷友網絡科技有限公司","0"?
ID 列和 ORDERGOODSDATE 列都是建立了索引的,同時也為 ORDERGOODSDATE 列建立了表分區。經過幾次測試,發現通過索引列排序進行查詢速度還是較慢(索引 Id 列:首次5秒,后面都是2.3秒;有索引的時間列:6秒;不排序:2秒)。
同時,我們還對分頁 SQL 進行的測試。目前有三種較為通用的分頁格式:
1.根據ROWID來分
select * from t_xiaoxi where rowid in(
? select rid from (
??? select rownum rn,rid from(
???? select rowid rid,cid from
???? t_xiaoxi? order by cid desc
??? ) where rownum<10000
? ) where rn>9980
)
order by cid desc;
2.按分析函數來分
select * from (
? select t.*,row_number() over(order by cid desc) rk from t_xiaoxi t
) where rk<10000 and rk>9980;
3.按ROWNUM來分
select * from(
? select t.*,rownum rn from(
??? select * from t_xiaoxi order by cid desc
? ) t where rownum<10000
) where rn>9980;
結果發現,原來的分頁格式,效率是最高的。下面的 SQL 查詢需要 4 秒:
select * from (
? select t.*,row_number() over(order by id ASC) rk from T_ENTERPRISETRANSACTION t
) where rk <= 5000010 and rk >= 5000000
由于我們的分頁 SQL 是自動生成的,所以格式方面我們要保留一定的通用性,同時性能不能太差。所以還是決定繼續保留原有的格式。
前面幾個優化方案沒有成功。我們就看了一下測試人員插入的一千條數據。原來這些數據的時間都是同一天的!!!造成了分區和索引失效。將數據按照真實場景錄入后,不到 1s 就查詢出來了。
另外,第 6 條:有 50 萬頁數據的頁面,不應該設計給客戶看到。所以我讓項目組的同這考慮是否需要刪除這個頁面,換一種實現方案。
第8條,不查全字段,只查 ID:測試后,也有了比較明顯的效果。
SELECT ID FROM (SELECT T.*, ROWNUM RNFROM ( SELECT ID FROM "T_ENTERPRISETRANSACTION" "T0" --order by T0.Id desc --order by T0.DBI_CreatedTime --order by T0.tradeDate) TWHERE ROWNUM <= 5000010 ) WHERE RN >= 5000000 --0.6秒 SELECT * FROM "T_ENTERPRISETRANSACTION" "T0" WHERE ID IN (7853679,7853680,7853681,7853682,7853683,7853684,7853685,7853686,7853687,7853688,7853689) --0.1秒一共只需要 0.7 秒。
?
常見問題三:大數據導入性能優化
公司產品的一個重要模塊是一個數據導入引擎。基于 WF4 引擎,配合一定的活動,來實現從文件到數據庫的導入。即:讀取文件 –> 大量數據格式轉換邏輯 & 大量業務邏輯 –> 導入數據庫。
由于邏輯非常復雜,所以我們并沒有把這些邏輯放到數據庫中去編寫存儲過程,而是基于內存中的領域實體來執行業務邏輯。
對于此程序的優化步驟:
這一步應該作為第一個步驟。開發者在對性能進行優化時,往往出現“想當然”地去分析、優化的行為,最終是花費了時間也沒有優化到點上!所以這里首重提出這一步驟。先讓工具去幫我們找到這些核心位置!
1.1 解決 ORM 中的 N+1 問題。
1.2 在內存中一次性準備好數據后,再插入到數據庫中。
1.3 對于導入大數據量到數據庫中,采用批量導入方案,而非逐條導入方案。
由于數據導入程序是 IO 密集型 + CPU 密集型操作,但是二者的運行階段不同。所以合理地采用多線程,可以大大提升執行效率。
使用多線程時,要注意線程安全的問題:盡量不要有太多的共享資源(文件、數據庫中的行);共享資源要加鎖(文件加鎖、內存加鎖、數據庫事務(事務的級別))。
另外,提前為各個線程準備好一些共用的數據,也可以優化一些不必要的 IO。
核心循環中,不要用 LINQ To Object:一個 Linq To Object 操作,至少生成了三個輕量級對象:一個委托、一個實現 IEnumerable 接口的對象,以及遍歷集合時,生成的一個 Enumerator。
核心循環中,要盡量減少循環的次數。例如:1000萬數據和100萬數據做循環匹配,不優化的循環就需要執行 1000萬*100萬次。所以我們需要引入一些算法來優化不必要的循環次數。
只需要優化核心循環,不需要優化所有的代碼。LINQ To Object 該用的時候,還要用。?
?
小結
本文對公司幾個項目遇到的共性問題進行了總結。
希望能對其它的項目組有所幫助。也希望能收集到更多的優化建議。
轉載于:https://www.cnblogs.com/zgynhqf/p/5609147.html
總結
以上是生活随笔為你收集整理的MIS性能优化常见问题与方案(辅助项目组性能优化的总结贴)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bootstrap-select实现下拉
- 下一篇: Hibernate中Entity实体类的