最近有朋友在我的知识星球里向我提问,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 的区别,请在文章下留言。