sap abap性能優化(三)

五、Sql優化

一、選擇條件 

v 在從數據庫中讀取數據時最好直接在select語句中加入選擇條件,從而直接限制篩選出符合條件的數據,而不建議讀出所有的數據然後用ABAP代碼來過濾篩選。

v 例如,不建議使用:

v Select * from zflight.

v Check : zflight-airln = ‘LF’ and zflight-fligh = ‘BW222’.

v Endselect.

v 建議使用:

v Select * from zflight where airln = ‘LF’ and fligh = ‘222’.

v Endselect.

v 這裏還要提醒的一點是關於 select *。通常這是一個懶惰的做法,程序員使用select * 的時候其實可能只有一兩個字段需要選擇。這實際上會顯著減慢程序的運行速度,並在整個系統上加載不必要的負擔。當應用服務器將這個請求發送到數據庫服務器的時候,數據庫服務器不得不將每一行數據的整個結構都發送回應用服務器。這樣既浪費CPU,又浪費網絡帶寬資源,尤其是在表結構很大的時候。

v 因此建議只選擇那些需要的字段,以便使數據庫服務器只傳遞少量數據回來。

 

二、集合函數 

v 可以使用ABAP提供的集合函數取代ABAP代碼來獲得最大或最小值。

v 不建議使用:

v Maxnu = 0.

v Select * from zflight where airln = ‘LF’ and cntry = ‘IN’.

v   Check zflight-fligh > maxnu.

v   Maxnu = zflight-fligh.

v Endselect.

v 建議使用:

v Select max( fligh ) from zflight into maxnu where airln = ‘LF’ and cntry = ‘IN’.

v 其它可用集合函數還有 min (最小值), avg (平均值), sum (求和) and count (數據選擇的行數).

 

三、視圖取代基本表 

v 很多時候 ABAP 程序員需要使用基本表和嵌套的選擇。其實我們應該查看一下是否有SAP已經提供的這些基本表的某些視圖可供使用,以便直接獲得想要的數據,而不用特別編寫代碼來獲取。

v 不建議使用:

v Select * from zcntry where cntry like ‘IN%’.

v Select single * from zflight where cntry = zcntry-cntry and airln = ‘LF’.

v Endselect.

v 建議使用:

v Select * from zcnfl where cntry like ‘IN%’ and airln = ‘LF’.

v Endselect.

v 視圖可以減少數據庫DB的讀寫操作, 當使用VIEW視圖的時候, 當被視圖jointable有數據更新操作的時候, 同時系統也會更新到這個view裏面, 使得它們之間的數據一樣, 所以使用視圖會對這些日常操作帶來效率問題.

 

四、“into table” 語句 

v 與其一行一行的讀取數據添加入內表,不如一次性取出所有數據行。

v 不建議使用:

v Refresh: int_fligh.

v Select * from zflight into int_fligh.

v   Append int_fligh.

v   Clear int_fligh.

v Endselect.

v 建議使用:

v Refresh: int_fligh.

v Select * from zflight into table int_fligh.

v 附加INTO CORRESPONDING FIELDS ... 把字段內容複製到具有相同名稱的目標字段。這種類型的複製會比使用INTO TABLE 左對齊複製到合適的內表或者明確列出目標字段的工作量大。 對於APPENDING CORRESPONDING FIELDS 和APPENDING TABLE 也是一樣的。

 

 

五、修改ABAP 代碼:判斷操作符NOT 和<>

v 如果WHERE 子句中的字段用操作符NOT 或<> 來指定,這些WHERE 條件就不能用於某個數據庫索引上的搜索。因此應該在可能的情況下用肯定形式來表達 SQL 語句。

v – 如果無法使用肯定的公式,例如,IN 清單過長,纔可以用NOT 來指定WHERE 條件,以減少傳輸的數據。

v – 對於下面兩個例子,索引範圍掃描都可以用於與字段MANDT、KUNNR 和AUART 一致的索引。 

v 1.SELECT vbeln erdat kunnr FROM vbak INTO TABLE g_itab_vbak WHERE kunnr IN g_kunnr AND NOT auart IN ('TA', 'KL', 'SO', 'ZBC').

v 對於上面的語句,只有字段MANDT 和KUNNR 可以用於索引搜索。在解釋SQL 中,可以看到一個索引範圍掃描。 

v 2.SELECT vbeln erdat kunnr FROM vbak INTO TABLE g_itab_vbak WHERE kunnr IN g_kunnr AND auart IN ('BV', 'WV', 'ZWK1', 'SM', space).

v 對於2的語句,字段MANDT、KUNNR 和AUART 都可以用於索引搜索。因此在解釋SQL 中可以看到一個索引範圍掃描的串聯。

 

六、使用二分查找(Binary Search)選項 

v READ命令使用順序查找數據表,這會降低處理速度。取而代之,使用binary search的附加命令,可以使用二分查找算法,可以幫助加快內表查找速度。 在使用binary search之前必須首先將內表排序,否則有可能找不到記錄,因爲二分查找反覆將查找區間對半劃分,如果要查找的值小於查找區間的中間位置的數據項值,則查找區間將縮小到前半個區間,否則查找將侷限於後半區間。要了解更多的關於二分查找算法介紹,請點擊這裏。

v 不推薦使用:

v Read table int_fligh with key airln = ‘LF’.

v 推薦使用:

v SORT int_fligh by airln.
Read table int_fligh with key airln = ‘LF’ binary search.

 

七、使用 “for all entries”

v 使用SELECT FOR ALL ENTRIES 是爲了把SELECT 語句從循環中分離出來。這個方法相當於再內表和數據庫表之間創建一個JOIN連接。

v 不推薦使用:

v Loop at int_cntry.

v Select single * from zfligh into int_fligh

v where cntry = int_cntry-cntry.

v Append int_fligh.

v Endloop.

v 推薦使用:

v IF NOT int_cntry[] IS INITIAL.

v   Select * from zfligh appending table int_fligh

v For all entries in int_cntry

v Where cntry = int_cntry-cntry.

v ENDIF. 

v 注意:內表不能爲空。如果選擇內表爲空,則選擇就沒有限制。通常,如果WHERE 子句的條件沒有參考內表的話,就不會被評估。

v • 在執行SELECT ... FOR ALL ENTRIES 之前,重複的內表條目應該被刪除。如果沒有刪除,就會從數據庫不必要的讀出 相同數據。

 

八、“where” 語句的正確結構 

v 當一個基本表有多個索引的時候, where 語句中的字段順序應該與索引的順序一致,無論第一索引還是第二索引。

v 在選擇一個索引的時候,優化機會檢查where語句中字段名,然後選擇一個與這些字段名排列順序一致的索引。

v 另外一個提示就是如果一個表是以 客戶端編號MANDT 開始的,而索引不是的話,則優化機很有可能不會使用那個索引。

v 在某些情況下,建議查看是否有新的索引可以加速程序的運行。這在訪問財務表的程序中會非常實用。

 

九、正確使用”inner join” 

v 當多個 SAP 表在邏輯上關聯的時候,總是建議使用右關聯 inner join 來從中讀取數據。這會降低網絡的負載。

v 以兩個表爲例:zairln 和 zflight。表 zairln 有字段 airln 存儲了航空公司的代碼,和字段 lnnam 存儲了航空公司的名稱。表 zflight 有航空公司代碼字段 airln, 以及其他字段存儲了航空公司運行的航班的詳細信息。

v 既然兩個表在邏輯上通過 airln 字段可以關聯,建議使用以下 inner join:

v Select a~airln a~lnnam b~fligh b~cntry into table int_airdet

v From zairln as a inner join zflight as b on a~airln = b~airln.

v 這樣就可以根據選擇條件來限制數據,以上inner join還可以增加 where 條件來進一步限制選擇條件。 

v 使用SQL語句裏面的JOIN時候, 應該避免JOIN的表不要超過3, 否則嚴重影響效率. 如果真的要JOIN3個以上的話, 而是使用SELECT ... INTO TABLE ... FOR ALL ENTRIES IN 以及 READ TABLE WITH KEY BINARY SEARCH.例如我們要提高讀取BSEG表的性能,首先我們會根據GJAHR主鍵從BKPF表取出部分數據到內表itab,然後使用FOR ALL ENTRIES IN itab WHERE BSEG~BELNR = itab~BELNR 這樣的的方法取得符合itab裏所有條件的BSEG數據.注意使用FOR ALL ENTRIES要先CHECK作爲條件的內表itab是否爲空,還有作爲WHERE的條件在這個內表裏面是否會有空值存在,否則無效.

 

 

十、使用 ABAP “Sort” 取代 “Order By”

v order by 命令是在數據庫服務器上執行的,而 sort 語句是在應用服務器上執行的。因此,與其在select語句中使用order by命令,不如將數據先讀取到內表中然後使用sort命令來將結果排序,因爲應用服務器上的執行速度要比數據庫服務器快。 

 

六、其他優化

其他: 

v 避免過得而頻繁的數據類型轉換,比如N轉換爲C,但是從N轉換成STRING卻是很快的,因爲操作STRINGCHAR類型少了比較長度的時間.

v 對於同一功能的函數和方法, 調用METHOD比調用FUNCTION要快. 

v 使用效率比較高的COLLECT, DELETE ADJACENT DUPLICATES FROM語句。 

內存優化方面:

v 1, 雖然ABAP擁有垃圾處理的機制, 但是這個是在程序運行完成後實現的. 所以我們儘量把無用的變量,內表,對象都釋放掉;

v 2, 儘量減少無用的靜態定義的變量,內表和對象, 因爲靜態定義的對象會在編譯開始就佔有內存空間;

v 3, 儘量減少網絡的傳輸負載, 比如在設計RFC遠程調用傳回的內表數據要儘量精簡, 數據量越大,CPU和內存需求越多;

v 4, 內存使用緊張的情況下, 使用FREE語句, 以及SQL語句的PACKAGE SIZE n 選項.

v SELECT vbeln erdat
FROM vbak
INTO TABLE li_vbak PACKAGE SIZE 50.


http://www.uwins.cn/

ERP交流羣379113944(驗證:來自博客)

微信服務號“ERP運維諮詢”(超多獵頭,求職招聘,很多幹貨分享,顧問遠程做項目)


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章