11.1. 數據庫編程方面優化
1. 不要使用 SELECT * ...,選擇需要的字段, SELECT * 既浪費CPU,又浪費網絡帶寬資源,還需占用大量的ABAP內存
2. 不要使用SELECT DISTINCT ...,會繞過緩存,可使用 SORT BY + DELETE ADJACENT DUPLICATES 代替
3. 少用相關子查詢,因為子查詢對外層查詢結果集中的每條記錄都會執行一次
4. 少用嵌套SELECT … ENDSELECT,可以使用聯合查詢或FOR ALL ENTRIES來替換,減少循環次數
5. 如果確定只查一條數據時,使用 SELECT SINGLE... 或者是 SELECT ...UP TO 1 ROWS ...
6. 統計時,直接使用SQL聚合函數,而不是將數據讀取出來后在程序里再進行統計
7. 使用游標讀取數據,這樣省掉了將從數據庫中的取記錄放入內表的INTO語句這一過程開銷
8. 多使用inner join,必要時才使用left join
9. inner join條件放置的位置應該按照 On、Where、Having的順序放,因為SQL條件的的執行一般是按這個順序來執行的,將條件放在最開始執行,則可過濾掉大部數據;但要注意Left Outer Join,是否可以將ON中的條件移動到Where從句則要考慮(如果真能放在Where從句中,則應該使用Inner Join,而非Left Outer Join,因為Where條件會過濾掉哪些包括在右表中不存在的左表數據),因為此時條件放在On后面與放在Where語句后面結果是不一樣的(因為不管on中的條件是否為真,左表中在右邊表不存在的數據也會被返回,但如放在where條件中,則會對On產生的數據再次過濾的條件,會濾掉不滿足條件的記錄——包括左表在右表中找不到的記錄,這時已經沒有left join的含義)
10. 要根據主鍵或索引字段查找數據,且WHERE從句中的條件字段需按INDEX字段順序書寫,且將索引字段條件靠前(左邊),如:在VBFA表中查找SO所對應的交貨單DN,因為如果直接到LIPS中找時,SO的訂單中號與行號在LIPS中非主鍵,但在VBFA是部分主鍵(VBFA中根據部分主鍵查找 SO -> DN; 根據索引查找 SO -> PO,VBFA-VBELN+VBFA-POSNN組合字段上創建了索引,即根據SO找PO時,不要從EKKN關聯表中查找,而是通過VBFA中查找。后來查看EKKN,發現在VBELN+VBELP字段上創建了索引,所以從VBFA與EKKO查找應該差不多,主要看哪個表數據量少的問題了)
檢查條件組合字段是否是主鍵,或者是上在上面創建了索引,避免條件組合字段即不是主鍵又沒有索引
11.使用部分索引字段問題:如果一個索引是由多個字段組成的,只使用一部分關鍵字段來進行查詢時,也是可以使用到索引,但使用時要注意要按照索引定義的順序且取其前面部分
12. 請根據索引字段進行ORDER BY,否則通過程序進行SORT BY。與其在數據庫在通過非索引字段進行排序,不如在程序中使用SORT BY語句進行排序,因為此情況下應用服務器上的執行速度要比數據庫服務器快(應用服務器上采用的是內存排序)
13.避免在索引字段上使用:
l not、<>、!=、IS NULL、IS NOT NULL
l 避免使用 LIKE,但LIKE '銷售組1000'和LIKE '銷售組1000%'可以用到,而LIKE '%銷售組1000'(百分號前置)則用不到索引
l 不要使用OR來連接多個索引字段;對於同一索引字段,可以使用IN來替代OR:
14.避免使用以下語句,因為使用這些語句時,不能使用 Table Buffer:
l Aggregate expressions
l Select distinct
l Select …for update
l Order by、group by、having從句
l Joins,使用JOIN時,會繞過SAP緩存,可以使用FOR ALL ENTRIES來代替
l WHERE從句中使用Sub queries(子查詢)
l WHERE從句中使用IS NULL條件
15.在下面情況下使用FOR ALL ENTRIES IN:
l 在循環內表 LOOP...AT Itab中循環訪問數據庫時
l 簇表是禁止JOIN的表類型, 當需要聯接簇表查詢數據時,如:BSEG(會計憑證)、KONV(條件表)
簇表一般是由多個表組成,簇表中的數據來自於多個表,有點像視圖,但不能直接通過簇表進行數據維護
l JOIN超過3個表會出現性能問題, 當使用JOIN聯接的表超過3個時
l 如果兩個表的數據非常大時(上百萬),使用JOIN進行聯合查詢會很慢,此時改用FOR ALL ENTRIES IN
16.使用內表批量操作數據庫,而不要使用工作區一條條操作,如:
SELECT ... INTO TABLE itab
INSERT dbtab FROM TABLE itab
DELETE dbtab FROM TABLE itab
UPDATE/MODIFY dbtab FROM TABLE itab
17.如果你使用 CLIENT SPECIFIED,需在WHERE從句第一個位置上指明 MANDT條件,否則使用不到索引