2. SAP S/4HANA分析架构基础

SAP S/4HANA 的分析能力并不是由某一个组件单独完成的,而是由 ABAP CDS 视图、虚拟数据模型(VDM)、分析引擎、Fiori 分析应用与嵌入式分析共同构成的一条协同链路。理解这条链路,是后续所有 CDS 建模、分析应用开发和嵌入式分析设计的基础。本节从“数据在哪里、由谁加工、由谁消费、结果如何呈现”四个问题出发,梳理各层职责与协作方式。

一、四层职责划分

在 S/4HANA 中,分析架构可以按职责划分为四层:

  • 数据层:由 S/4HANA 标准业务表(如 ACDOCA、VBAK、MARA 等)以及自定义表承载原始数据。这些表是分析数据的最终来源,但通常不直接暴露给分析消费者。
  • 建模层:由 ABAP CDS 视图承担。CDS 视图在数据库层执行,通过 @Analytics、@Semantics、@VDM 等注解声明分析语义,形成可复用的虚拟数据模型。
  • 引擎层:由 ABAP 分析引擎(Analytics Engine)和 SAP HANA 计算引擎组成。分析引擎负责解析 CDS 视图中的分析注解,生成查询、聚合、层级、变量等运行时行为。
  • 消费层:由 Fiori 分析应用(Analytical List Page、Overview Page、Design Studio 等)和嵌入式分析(Embedded Analytics,如 KPI 磁贴、分析列表嵌入到 Fiori 事务应用)组成,负责把分析结果以可视化方式呈现给业务用户。

这四层之间不是简单的线性调用,而是通过 VDM 分层(Interface → Composite → Consumption)实现复用与解耦。Interface 层贴近物理表,Composite 层做业务组合,Consumption 层面向具体分析场景。Fiori 应用和嵌入式分析通常只消费 Consumption 层视图,从而保证上层应用不因底层表结构变化而频繁调整。

二、协同工作机制

当用户在 Fiori 分析应用中打开一个分析列表页时,实际发生的协同过程如下:

  1. Fiori 应用通过 OData 服务(通常由 @OData.publish: true 或 SADL 生成)向 ABAP 后端发起查询请求,请求中携带筛选条件、变量值和分页参数。
  2. ABAP 分析引擎接收请求,解析目标 CDS 视图上的分析注解,确定聚合维度、度量、层级关系和变量替换规则。
  3. 分析引擎将逻辑查询下推到 SAP HANA 数据库,由 HANA 的列式存储和计算引擎执行实际聚合与计算。
  4. 结果集返回分析引擎后,按 OData 协议封装为实体集,回传给 Fiori 应用。
  5. Fiori 应用根据返回的元数据和结果渲染图表、表格或 KPI 磁贴;嵌入式分析场景中,同一结果集可能被嵌入到事务应用的侧边栏或概览区。

这条链路的关键在于:CDS 视图既是数据模型,也是分析语义的载体。分析引擎不直接读表,而是读 CDS 视图的注解;Fiori 应用不直接写 SQL,而是通过 OData 消费 CDS 视图。因此,CDS 视图的质量直接决定了分析应用的性能、可维护性和可扩展性。

三、VDM 分层与消费路径

VDM 分层是 S/4HANA 分析架构中最重要的组织原则。以销售分析为例:

  • Interface 层:I_SalesDocument 直接基于 VBAK/VBAP 等表,提供销售凭证的基础字段和关联。
  • Composite 层:C_SalesDocument 在 Interface 层之上组合客户、物料、组织等维度,形成业务可理解的销售凭证视图。
  • Consumption 层:C_SalesAnalysis 面向分析场景,声明度量(如净额、数量)、维度(如客户、产品、期间)和变量(如日期范围、公司代码),供 Fiori 分析应用直接消费。

这种分层的实际价值在于:当业务表结构变化时,只需调整 Interface 层;当业务规则变化时,只需调整 Composite 层;当分析需求变化时,只需调整 Consumption 层。各层之间通过稳定的字段名和注解契约解耦,避免“牵一发而动全身”。

四、嵌入式分析与 Fiori 分析应用的差异

Fiori 分析应用和嵌入式分析虽然共享同一套 CDS 视图和分析引擎,但在消费方式上有明显差异:

对比维度 Fiori 分析应用 嵌入式分析
入口 独立 Fiori 应用(如 ALP、OVP) 嵌入在事务应用或概览页中
交互方式 筛选、钻取、变量、层级导航 KPI 磁贴、迷你图、侧边栏分析列表
典型 CDS 注解 @Analytics.query: true、@AnalyticsDetails @Analytics.dataCategory: #CUBE、@UI.chart
性能关注点 大数据量聚合、层级展开 轻量级、快速响应、与事务上下文联动

嵌入式分析通常要求更低的延迟和更强的上下文关联能力。例如,在采购订单事务应用中嵌入“该供应商历史交货准时率”KPI 磁贴时,CDS 视图需要接受采购订单号作为输入参数,并快速返回聚合结果。这类场景下,CDS 视图的 @Analytics.dataCategory 和参数化设计尤为关键。

五、协同工作机制示意图

下图展示了从业务表到 Fiori 分析应用与嵌入式分析的完整协同链路,包括 VDM 三层、分析引擎和消费层的交互关系。

数据层 · S/4HANA 业务表 ACDOCA VBAK / VBAP MARA / MARC EKKO / EKPO 自定义表 建模层 · 虚拟数据模型(VDM) Interface 层 I_SalesDocument 贴近物理表 · 基础字段 Composite 层 C_SalesDocument 业务组合 · 维度关联 Consumption 层 C_SalesAnalysis 分析语义 · 度量/变量 引擎层 · 分析引擎与 HANA 计算引擎 ABAP Analytics Engine SAP HANA 列式计算引擎 OData / SADL 服务生成 消费层 · Fiori 分析应用与嵌入式分析 Fiori 分析应用 ALP / OVP / Design Studio 嵌入式分析 KPI 磁贴 / 侧边栏分析列表 业务用户 筛选 / 钻取 / 决策

六、关键注解与协同要点

要让上述链路正常工作,CDS 视图必须正确声明分析注解。以下是一段示例代码,展示 Consumption 层视图如何声明分析语义:

@AbapCatalog.sqlViewName: 'ZCSALESANA'
@Analytics.dataCategory: #CUBE
@Analytics.query: true
@OData.publish: true
@AccessControl.authorizationCheck: #CHECK
define view Z_C_SalesAnalysis
  as select from Z_C_SalesDocument
{
  key SalesDocument,
      Customer,
      Product,
      @Semantics.amount.currencyCode: 'Currency'
      @DefaultAggregation: #SUM
      NetAmount,
      @Semantics.quantity.unitOfMeasure: 'Unit'
      @DefaultAggregation: #SUM
      OrderQuantity,
      Currency,
      Unit,
      @Semantics.systemDate.createdAt: true
      CreatedDate
}
where SalesDocumentType = 'OR'

这段代码中,@Analytics.dataCategory: #CUBE 告诉分析引擎这是一个多维分析立方体;@Analytics.query: true 表示该视图可直接作为分析查询使用;@OData.publish: true 使视图自动生成 OData 服务供 Fiori 消费;@DefaultAggregation: #SUM 声明度量字段的默认聚合方式;@Semantics 注解则建立金额与币种、数量与单位之间的语义关联,确保分析引擎在聚合时正确处理单位换算和币种转换。

在实际项目中,建议先确认 Consumption 层视图的注解是否完整,再检查 OData 服务是否已激活,最后验证 Fiori 应用的目标映射是否正确。这三步是排查“分析应用无数据”问题的基本顺序。

七、协同工作机制的实践意义

理解这套协同机制,对后续建模工作有直接指导意义:

  • 建模时优先考虑 VDM 分层,避免在 Consumption 层直接引用物理表,否则底层表结构变化会直接冲击分析应用。
  • 分析注解必须与消费场景匹配:面向 ALP 的视图需要 @Analytics.query: true,面向嵌入式 KPI 的视图需要 @Analytics.dataCategory: #CUBE 并配合参数化设计。
  • 性能优化应优先在 CDS 视图层完成,例如通过 @AccessControl 下推权限过滤、通过 @AnalyticsDetails.query.axis 控制维度分布,而不是在 Fiori 层做二次过滤。
  • 嵌入式分析与 Fiori 分析应用共享同一套 CDS 视图时,应通过参数化或视图变体区分不同消费场景,避免为每个场景重复建模。