考試系統在進行壓力測試時發現,並發量高之後出現了按鈕無反應,試題答案不能寫到資料庫的問題,於是針對這些核心問題,進行了最佳化。
資料庫方面:
Select語句:Select * from TEB_VB_XZTRecord改為select 必須的列 form TEB_VB_XZTRecord,之前看的教學視頻裡就講過最好別用*,由於查詢了不必要的列,所以導致了低效率。
insert最佳化:考試業務的原因,需要把查詢出來的試題,一條條的插入到資料庫中。最佳化前:迴圈+每次插入一條的insert語句。最佳化後:insert 表名(欄位名) select (欄位名) from 表名 where questionID in(,,,,,,,)
這種最佳化在insert語句中用了select字句和in關鍵字,相當於在資料庫執行了查詢之後,直接進行了查詢,沒有通過java項目的一次次的迴圈。之前想用一個insert+多個value的方法,發現這種方式在mysql中行的通,但在oracle中行不通。
程式設計和演算法最佳化:
演算法經常受個人思路的影響,比如對複用認識深刻,幹過的事情就把成果儲存下來,以後再用就高效了。程式設計也是一樣。
緩衝相同資料
考生的考試卷面,需要由考試資訊、個人資訊,考試卷面分值分布,試卷內容 四塊內容組成,其中考試資訊和卷面分值分布 對每個考生都相同,因此將相同的資訊進行緩衝,就減少了大量的查詢,而不是用一次查一次。
提前謀劃,提前準備
在大並發量時,可以提前乾的事就提前幹,就像請人在自己家吃飯,到了吃飯的點臨時準備飯菜,肯定手忙腳亂,提前準備出來到時候就悠閑了。
對於考試系統的抽捲來說:考生考試時,每個考生都隨機從題庫抽取一套試卷。這種方法包含了大量的查詢和一個迴圈,因此對效能要求較高,並且大並發量時導致了系統根本沒反應。
第一次最佳化:在考試前為考生抽好試卷,考生登入時只需從答題記錄表查詢即可,這樣是把抽題的過程提前準備好了。
第二次最佳化:考慮到第一次最佳化中扔需要大量的查詢,這次最佳化的邏輯是 抽取固定的卷數,比如抽取50套,每套卷有一個卷號,考試前將50套卷載入到記憶體中,考生隨機抽取到一個卷號,然後根據卷號從記憶體中拿試卷,這樣只要查詢一次,然後其他考生都可以從記憶體中擷取試卷,避免了大量的查詢。
將事情分開幹
非常忙的時候,把可以後推推的事情推後點,合理規劃好資源和時間。答卷過程中,將客觀題判分的環節移到了教師判分邏輯中,因為正確答案需要查詢,所以在答題時會同時有大量的查詢和更新操作,去掉了判分,答題時就只有更新了。
再有就是對String的最佳化,因為考試系統需要將試題顯示在介面,因此需要在後台將試題拼好串,顯示在前台,當時用了String,但String不是動態擴容的,只會複製原來的String,加上新內容後新生產一個。因此存在著大量的儲存浪費,改為了StringBuffer以後,對記憶體的要求小了很多。