後臺程式效能優化
一. 優化原則:
1、減少資料庫訪問次數
(1) 使用資料快取的存取方式
(2) 使用批量處理的方式
2、減少SQL語句的執行時間
(1) 使用佔位符的訪問方式
(2) 優化SQL的執行計劃(比如使用資料庫索引或者調整SQL)
3、 減少程式執行的時間
(1) 使用非同步呼叫代替同步呼叫
(2) 使用本地API方式代替遠端呼叫(比如WebSerivce)
(3) 減少同步塊或者同步方法的使用
(4) 減少IO讀寫
4、減少請求壓力
(1) 使用應用叢集部署方式分擔掉伺服器的壓力
(2) 將靜態檔案和動態檔案分離部署,減少J2EE容器的壓力
二. 高效Java:
1、儘量避免不必要的方法呼叫
原則:在Java中,一切都是物件,如果有方法(Method)呼叫,處理器先要檢查該方法是屬於哪個物件,該物件是否有效,物件屬於什麼型別,然後選擇合適的方法並呼叫。儘可能在外層確定是否一定要執行該方法。
優化前:
- public void CallMethod(int i ){
- if( i ==0 ){
- return;
- }
- ... // 其他處理
- }
- int i = 0;
- ...
- CallMethod(i);
優化後:
- int i = 0;
- ...
- if( i ==0 ){
- CallMethod(i);
- }
2、儘量避免不必要的物件建立
原則:當一個物件是用new進行初始化時,其建構函式鏈的所有建構函式都被呼叫到,所以new操作符是很消耗系統資源的,new一個物件耗時往往是區域性變數賦值耗時的上千倍。同時,當生成物件後,系統還要花時間進行垃圾回收和處理。儘量少用new來初始化一個類的例項, 當new建立物件不可避免時,注意避免多次的使用new初始化一個物件,儘量在使用時再建立該物件。
優化前:
- NewObject object = new NewObject();
- int value;
- if(i>0 )
- {
- value =object.getValue();
- }
優化後:
- int value;
- if(i>0 )
- {
- NewObject object = new NewObject();
- Value =object.getValue();
- }
3、儘量減少對變數的重複計算體
原則:迴圈是比較重複執行的地方,如果迴圈次數很大,迴圈體內不好的程式碼對效率的影響就會被放大而變的突出。當有較大的迴圈時,應該檢查迴圈內是否有效率不高的地方,尋找更優的方案加以改進。
優化前:
- Vector vect = new Vector(1000);
- ...
- for( int i=0; i<vect.size(); i++){
- ...
- }
優化後:
- int size = vect.size();
- for( int i=0; i<size; i++){
- ...
- }
4、生成物件時,分配合理的空間和大小
原則:Java中的很多類都有它的預設的空間分配大小,對於一些有大小的物件的初始化,應該預計物件的大小,然後使用進行初始化。
StringBuilder builder = new StringBuilder(100);
5、使用StringBuilder代替String
原則:String是用來儲存字串常量的,如果要執行“+”的操作,系統會生成一些臨時的物件,並對這些物件進行管理,造成不必要的開銷。如果字串有連線的操作,替代的做法是用StringBuilder的append方法,StringBuffer是有同步機制的,效率上沒有StringBuilder快。
6、控制查詢返回的結果條數
原則:當查詢返回的資料量過大時,通過擷取前面100條的資料返回,不然將嚴重影響系統的響應時間。
7、多執行緒不能使用HashMap
原則:HashMap沒有同步機制,用於多執行緒的頻繁讀寫會產生執行緒死鎖的情況。推薦使用ConcurrentHashMap來代替HashMap,在初時化時儘量傳入大小容量。
8、不要在迴圈中使用try…catch
原則:在迴圈中使用try…catch的話會造成多次異常判斷邏輯,儘量做到一個方法最多隻有一個try…catch塊。
9、使用高效的HashMap的遍歷
低效率的遍歷方式:
- Map map = new HashMap();
- Iterator iter = map.keySet().iterator();
- while (iter.hasNext()) {
- Object key = iter.next();
- Object val = map.get(key);
- }
高效率的遍歷方式:
- Map map = new HashMap();
- Iterator iter = map.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry entry = (Map.Entry) iter.next();
- Object key = entry.getKey();
- Object val = entry.getValue();
- }
第一種對於keySet其實是遍歷了2次,一次是轉為iterator,一次就從hashmap中取出key所對於的value。
第二種entryset只是遍歷了第一次,他把key和value都放到了entry中,所以會比第一種快。
三. 高效SQL
1、儘量不用萬用字元“%”或者“_”作為查詢字串的第一個字元
當萬用字元“%”或者“_”作為查詢字串的第一個字元時,索引不會被使用。比如用 T 表中 Column1 LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成 Column1 ‘X5400%’ OR Column1 LIKE ‘B5400%’ 則會利用 Column1 的索引進行兩個範圍的查詢,效能肯定大大提高。
2、儘量EXISTS替換IN 操作符(主要考慮索引是否能用上的問題)
基本上所有的 IN 操作符都可以用 EXISTS 代替,在選擇 IN 或 EXIST 操作時,要根據主子表資料量大小來具體考慮。
3、用 UNION ALL 代替 UNION
UNION 是最常用的集操作,使多個記錄集聯結成為單個集,對返回的資料行有唯一性要求, 所以 oracle 就需要進行 SORT UNIQUE 操作(與使用 distinct 時操作類似),如果結果集又 比較大,則操作會比較慢;
UNION ALL 操作不排除重複記錄行,所以會快很多,如果資料本身重複行存在可能性較
小時,用 union all 會比用 union 效率高很多!
4、SELECT子句中避免使用“*”號
ORACLE在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味著將耗費更多的時間。
5、儘量用 NOT EXISTS 或者外連線替代 NOT IN 操作符
因為 NOT IN 不能應用表的索引。
6、儘量不用“<>”或者“!=”操作符
不等於操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。比如:a<>0
改為 a>0 or a<0
參考資料: http://chenjc-it.iteye.com/blog/1565143