最近有朋友在我的知識星球裡向我提問,SAP ABAP CDS view 的 INNER JOIN 和 Association 的功能可以理解為一樣嗎?
(關於加入我的知識星球的方式,請移步本文文末)
本文就來聊一聊這個話題。既然 CDS view 裡同時支援了 INNER JOIN 和 Association 兩種操作,那說明二者必然存在一些差異。
首先建立一個包含 INNER JOIN 的 CDS view,將 sflight 和 spfli 兩張表透過共同的 carrid 欄位連線在一起,sqlViewName 取名為 ZJERRYCDSJ.
這個 CDS view 將 sflight 的三個欄位和 spfli 資料庫表的兩個欄位 airpfrom 和 airpto 暴露給消費者。
然後我們用下面這條 ABAP 語句從 CDS view 裡僅僅讀取來自 sflight 資料庫表的兩個欄位。
DATA: lt_data TYPE TABLE OF ZJERRY_CDS_VIEW_JOIN.
SELECT carrid, connid INTO CORRESPONDING FIELDS OF TABLE @lt_data FROM zjerry_cds_view_join.
我們開啟 ST05 跟蹤模式,執行上面的報表,檢視生成的 SQL trace,透過 sqlViewName 指定為 ZJERRYCDSJ,即可定位到訪問 CDS view 的那條 SQL 語句。
我們在 ST05 事物碼裡選擇 Edit->Display Execution Plan->For Recorded Statement
,即可檢視到上面那條 SQL 語句在執行時的執行計劃:
執行計劃如下圖所示:
綠色區域的 FDA READ,意思是快速資料訪問 (Fast Data Access,縮寫為 FDA),這是一種在 SAP ABAP 環境中進行資料讀寫訪問的協議。它針對 SAP HANA 為 OPEN SQL SELECT 等語句執行時提供了專門的最佳化。在快速資料訪問場景裡,SAP ABAP 內表的資料透過一種特殊的方式傳輸到資料庫,處理完畢後返回應用層。FDA 避免了按欄位級別(field-wise)進行 ABAP 資料複製和資料格式轉換的額外開銷,減少資源利用率以提高應用效能。
FDA 從 SAP ABAP 核心 7.42 版本引入,對於一般的 ABAP 開發人員來說是透明的,僅僅能夠在 ST05 Execution 裡觀察到。
上圖的執行計劃裡,我們在 SELECT 語句裡只訪問了來自 sflight 表的 carrid 和 connid 兩個欄位,但是從執行計劃的藍色區域能觀察到,sflight 和 spfli 的資料庫表 INNER JOIN 仍然發生了。
我個人把這種行為稱為 Eager Join(貪婪 Join),類似 Angular Feature Module 的 Eager Load(貪婪載入)。
在 Eager Join 的場景下,表 Join 一定會發生,無論被 Join 的表的欄位在當前事務裡是否會被讀取,這造成了不必要的效能開銷。在 Angular Feature Load 場景裡,以 Cart Feature Module(功能模組) 為例,如果採取預設的貪婪載入機制,那麼使用者即使只是在頁面隨便瀏覽一下商品,購物車模組也會被瀏覽器載入,這影響了電商頁面的首屏載入時間。
Eager 的反義詞當然就是 Lazy,Lazy Load 就是懶載入,延時載入,按需載入。將 Cart Feature Module 配置成 Lazy Load,其表現形式就是直到使用者點選新增到購物車按鈕,或者直接點選右上角的購物車圖示後,才會從瀏覽器裡看到 Cart 功能模組的載入。
同理,CDS view 的 Association 能實現 Lazy Join.
我們使用下圖的程式碼,建立一個 CDS view,透過 Association,將表 SFLIGHT 和 SPFLI 連線起來。乍一看,實現的功能和之前透過 Join 開發的版本沒有任何區別。
我們編寫一段 ABAP 程式碼來消費這個 CDS view.
在這段 ABAP 程式碼裡,只讀取 sflight 資料庫表的 carrid 和 connid 兩個欄位。
DATA: lt_data TYPE TABLE OF ZJERRY_CDS_VIEW_ASS.
SELECT carrid, connid INTO CORRESPONDING FIELDS OF TABLE @lt_data FROM zjerry_cds_view_ass.
從 ST05 的 Trace 中,我們看不到 spfli 被 Join 的跡象。
將 ABAP 報表稍作修改,不僅讀取 sflight 資料庫表的欄位,而且透過 CDS view 裡的名為 _flight 的 Association,讀取透過 Association 關聯的另一端 spfli 表的 airpfrom 和 airpto 欄位。
最後在 ST05 Trace 裡,能觀察到此時 spfli 資料庫表確實透過 LEFT OUTER JOIN 同 sflight 建立了連線。
如果大家知道更多關於 CDS view INNER JOIN 和 Association 的區別,請在文章下留言。