Fork me on GitHub

SAP S/4嵌入式分析——虚拟数据模型(VDM)

  在本文中,我会通过CDS视图来介绍虚拟数据模型(Virtual Data Model,以下简称VDM)。

  在SAP HANA平台出现后,SAP的业务应用开发模式已经产生了变化,新的经验法则是:尽可能在数据库中做更多的事情(PUSH DOWN),以得到最佳的性能。          

 

  本文链接:https://www.cnblogs.com/hhelibeb/p/9223993.html

嵌入式分析

  SAP S/4嵌入式分析是S/4的一部分,用于对业务数据执行复杂的实时报表和分析。SAP S/4嵌入式分析的关键架构组件包括SAP HANA数据库,VDM,分析引擎(嵌入式SAP BW),OData服务,和如下图所示的接口。

 

  本文将介绍其中的VDM。

CDS视图

  为了在应用开发中利用SAP HANA的优点,SAP引入了新的数据建模基础设施,名为Core Data Service(以下简称CDS)。通过CDS,数据模型会在数据库而非应用服务器中定义和消费。CDS也提供了传统数据建模工具的兼容性,包含支持概念建模和关系定义,内置函数和扩展。

  技术上讲,CDS是提供数据定义语言(DDL)的加强版SQL,用于在数据库中定义富语义数据库表/视图(CDS entity)和用户定义的类型。增强包括:

  • Expression:用于在数据模型中计算和查询。
  • Association:在概念层上,通过简单的path expression代替join(关于Association可参考之前的文章)。
  • Annotation:通过附加的(特定领域的)元数据来丰富数据模型。

  CDS在ABAP和SAP HANA中都得到了原生支持。数据模型通过数据定义语言(DDL)表达,并且定义为CDS视图,可以在ABAP程序中通过Open SQL语句访问。CDS为业务和开发提供了一系列优点,包含:

  • 富语义数据模型:CDS基于众所周知的实体-关系模型,并且实质上是声明式的,非常接近概念思维。
  • 兼容任何数据库平台:CDS会被生成为受管理的Open SQL视图,并且原生地集成进入SAP HANA层。这些基于Open SQL的视图得到了所有主流数据库供应商的支持。
  • 高效:CDS提供了多样化和高效的内置函数,例如SQL运算符,聚合和表达式,来帮助开发者构建视图。
  • 支持annotation:CDS语法支持特定领域的annotation,可以轻松的被其他组件利用,比如UI,分析和OData服务。
  • 支持概念关联 conceptual associations):CDS帮助你定义association,作为不同视图的关系。Path expression可以用于在关系间导航。association引入了抽象的外键关系和join,来对可消费的entity进行导航。
  • 可扩展性:客户可以扩展SAP定义的CDS视图,扩展字段将随其使用层次结构自动添加到CDS视图中。

VDM

  在HANA之前,查询ERP系统中的大量数据集会花很多时间,并会降低系统的整体性能。数据仓库可以通过高级建模技术创建持久化的数据模型,以提高查询性能。SAP HANA去除了ERP中的性能问题,使我们能够直接在ERP中创建虚拟数据模型(VDM),并提供令人难以置信的高性能

  VDM是什么?VDM是富语义CDS视图的结合,它将ERP源表的数据符合逻辑地结合到一起,创建成为有意义的数据集,并且可以被前端工具便利地消费

  VDM的核心原理是在现有的S/4数据库模型之上构建语义层,隐藏它的技术细节。基于提供的内容和复用选项,VDM中的CDS视图被分为接口视图或消费视图,如下:

 

私有视图

  私有视图(Private Views)实际上不是提供给终端用户消费的视图,它是技术驱动的辅助视图。引入私有模型是为了帮助底层数据模型到公共视图模型的转换。私有CDS视图的名字前缀是P_。不建议修改或扩展它们。

接口视图

  接口视图(Interface views)是VDM最重要的组成部分。接口视图组成了可复用的entity视图,在业务语义是定义上的重点。接口视图对任何消费者而言都是公开的、稳定的并且可复用的。公共接口视图的结构需要不受correction、补丁和升级的影响。

  接口视图分两种:

  基本接口视图(Basic interface Views)代表没有数据冗余的核心entity,即对每个核心entity做单一的表示,(比如,正好一个客户或者销售订单)并且只带有依赖于核心entity自身的、无法从其他字段计算得到的字段。基本视图组成了低冗余模型和SAP Business Suite数据库表的简单投影。

  组合接口视图(Composite Interface Views)继承自多个简单接口视图,也许会有关联、聚合和复杂计算。它们可以属于特定消费域,或者被复用,根据设计,它们总是暴露冗余的数据。按照实际的使用情况,组合接口视图可以分为很多层。

消费视图

  如名字所示,消费视图(Consumption Views)是暴露给终端用户消费的视图。消费视图会使用到一个或更多接口视图。消费视图是共用的特定领域视图,用于分析、搜索和事务应用。VDM建模的指导原则是,数据库表一定不可以被消费视图直接访问(即不可以绕过接口视图)

扩展包含视图

  扩展包含视图(Extension include Views)用于暴露自定义新字段。可以扩展SAP发布的扩展包含视图,以条件附加字段。自定义扩展包含视图会在单独的DDL源中创建和传输。

  总之,在高层上,CDS视图从数据库表得到数据,这些视图又会被其它CDS视图读取,VDM就是由所有的这些CDS视图组成。没有任何持久化过程,一切都是实时的。

Annotation

  Annotation用于描述CDS视图,为CDS视图中的字段提供语义和意义。

  • 它可以应用在整个CDS视图entity上;
  • 它可以指定SELECT列表中特定的字段的语义;
  • 总是在@符号后面

  这面是annotation的列表:https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abencds_annotations_sap.htm

  也可以通过以下路径访问:ABAP – Keyword Documentation > ABAP – Dictionary > ABAP CDS in ABAP Dictionary > ABAP CDS – Syntax > ABAP CDS – Annotations

  下面是用于VDM的定义整个CDS视图的一些关键的annotation:

Annotation Description
VDM.viewType 定义VDM视图的类型
Analytics.dataCategory 分析查询可以在CDS视图之上定义。通过指定数据分类,开发者可以提供指令和hints,告诉analytic manager如何解释各个实体。
Analytics.dataExtraction.enabled 应用开发者通过该annotation标记适合于数据复制的视图(例如,必须为海量数据提供增量复制能力)。
Analytics.query 通过标记CDS视图,开发者可以指定暴露给analytic manager的视图。这类视图会被analytic manager解释为分析查询。
ObjectModel.dataCategory 定义数据分类(#TEXT 或 #HIERARCHY)
ObjectModel.representativekey Most specific element (field or managed association) of the primary key (indicated by the keyword KEY) that represents the entity which the view is based on
AccessControl.authorizationCheck 针对指定的CDS视图启用行级别权限控制

/名词解释:analytic manager是一个BW概念,它提供OLAP功能和服务,以及BW集成规划和分析过程设计的服务。

  

  因为我还是个BW开发者,我找了几个最重要的VDM的annotation来和BW对象对比:

Annotation: @VDM.viewType

Value Description BW 对等物
#BASIC 组成核心基础的视图,无数据荣誉,它只是从数据库物理表的SELECT。 等于ADSO(高级数据存储对象),即通过某些ETL后的raw data。
#COMPOSITE 提供从基础视图继承和/或组合而成的数据 等同于Composite Provider,是允许进行join和union的虚拟数据层。
#CONSUMPTION 为特定应用目的服务的视图,也许会基于公共接口视图定义(比如BASIC 视图或COMPOSITE视图) 等于BW Query,可以指定特殊的样式,变量,RKF,CKF,总计,等等。

Annotation: @Analytics.dataCategory

Value Description BW 对等物
#DIMENSION 表示主数据的视图需要有annotation:ObjectModel.dataCategory: #DIMENSION 等于Infoobject Attributes
#FACT 事实表表示业务数据(星型模型的中心)通常包含度量。这些视图通常是复制所必须的,因此,他们不能和主数据视图join。 等于从一个单一数据源加载的ADSO,没有任何主数据。
#CUBE CUBE也代表事实数据,和FACT很像,但是CUBE不必是无冗余的。这意味着它可以和主数据join。查询基本都是构建在CUBE之上的,CUBE从FACT复制数据。 等于从单一/多个数据源加载的ADSO,和主数据的attributes/texts/hiererachies连接。

Annotation: @Analytics.dataExtraction.enabled

Value Description BW 对等物
#TRUE 应用开发者用这个annotation表示视图适合于数据复制。(比如对于大量数据必须提供增量复制能力) N/A
#FALSE 不适合数据复制 N/A

 

Annotation: @ObjectModel.dataCategory

Value Description BW 对等物
#TEXT

表示该entity代表文本,通常一个key元素是语言。

NOTE: 在VDM中,文本视图总是独立于语言的。

等于 infoobject Texts/descriptions
#HIERARCHY 表示该entity代表层次相关的数据。可以是header相关的数据或者结构信息。 等于 infoobject Hierarchy

 

Annotation: @AccessControl.authorizationCheck

Value Description BW 对等物
#NOT_REQUIRED 不存在针对该视图的DCL(行级别安全对象),所以不会对该CDS视图进行权限检查,所有数据都会被展示。 N/A
#CHECK 存在针对该视图的DCL(行级别安全对象),会对该CDS视图进行行级别权限检查。 有点像 BW authorizations
#NOT_ALLOWED 存在针对该视图的DCL(行级别安全对象),但是不会进行行级别的权限检查。 N/A

 

  现在我们看过了CDS的主要annotation,我们将会进一步审视VDM的详细架构。

  注意这些概念和BW环境中的那些有多么相似。我们在CDS中有文本和维度,我们可以一次构建、多次在不同的事务性CDS视图中重用它们。

  假设这是在构建一个物料维度和文本视图。 你只需要建立它一次,因为基础表不会改变(MARA和MAKT)。 但是,对于需要物料描述或属性的各个事务模型(销售,交货,盈利分析,库存等),你可以重复利用该维度和文本视图。

例子

  下面是有关上述各个CDS视图的细节:

TEXT

 

@AbapCatalog.sqlViewName: 'ZBTMATERIAL'
@ObjectModel.dataCategory: #TEXT
@Analytics: { dataCategory: #TEXT, dataExtraction.enabled: true }
@AccessControl.authorizationCheck: #NOT_REQUIRED
@VDM.viewType: #BASIC
@EndUserText.label: 'Material Text'
@ObjectModel.representativeKey: 'Material'

define view Zbt_Material as 
  select from makt 
        { 
          @ObjectModel.text.element:  [ 'MaterialName' ] 
          key makt.matnr as Material, 
          @Semantics.language: true
          key makt.spras as Language,
          @Semantics.text: true 
              makt.maktx as MaterialName}


where makt.spras = $session.system_language

DIMENSION

 

@AbapCatalog.sqlViewName: 'ZBDMATERIAL'
@Analytics: { dataCategory: #DIMENSION, dataExtraction.enabled: true }
@VDM.viewType: #BASIC
@AbapCatalog.compiler.compareFilter: true
@EndUserText.label: 'Material Attributes'
@ObjectModel.representativeKey: 'Material'
@AccessControl.authorizationCheck: #NOT_REQUIRED

define view Zbd_Material as select from mara 

association [0..1] to Zbt_Material           as _Text           on $projection.Material      = _Text.Material
association [0..1] to Zbd_MaterialType       as _MaterialType   on $projection.MaterialType  = _MaterialType.MaterialType
association [0..1] to Zbd_MaterialGroup      as _MaterialGroup  on $projection.MaterialGroup = _MaterialGroup.MaterialGroup
association [0..1] to I_UnitOfMeasure        as _BaseUnit       on $projection.MaterialBaseUnit = _BaseUnit.UnitOfMeasure
association [0..1] to I_UnitOfMeasure        as _WeightUnit     on $projection.MaterialWeightUnit = _WeightUnit.UnitOfMeasure
association [0..1] to Zbt_Storage_Conditions as _StorCond       on $projection.StorageCondition = _StorCond.StorageCond

     { @EndUserText.label: 'Material'
       @ObjectModel.text.association: '_Text'
          key mara.matnr as Material, _Text,
          
       @ObjectModel.foreignKey.association: '_MaterialType'
       @EndUserText.label: 'Material Type'  
              mara.mtart as MaterialType, _MaterialType,
       @ObjectModel.foreignKey.association: '_MaterialGroup'
       @EndUserText.label: 'Material Group'        
              mara.matkl as MaterialGroup, _MaterialGroup,
       @EndUserText.label: 'Base Unit of Measure'  
       @Semantics.unitOfMeasure: true
       @ObjectModel.foreignKey.association: '_BaseUnit'
              mara.meins as MaterialBaseUnit, _BaseUnit,                
       @EndUserText.label: 'Gross Weight'  
       @Semantics.quantity.unitOfMeasure: 'MaterialWeightUnit'              
       @DefaultAggregation: #NONE
              mara.brgew as MaterialGrossWeight,
       @EndUserText.label: 'Net Weight'  
       @Semantics.quantity.unitOfMeasure: 'MaterialWeightUnit'
       @DefaultAggregation: #NONE
                     mara.ntgew as MaterialNetWeight,              
       @EndUserText.label: 'Weight Unit'
       @Semantics.unitOfMeasure: true
       @ObjectModel.foreignKey.association: '_WeightUnit'
              mara.gewei as MaterialWeightUnit, _WeightUnit,
                            
              mara.mfrnr as MaterialManufacturerNumber,
              mara.mfrpn as MaterialManufacturerPartNumber,
       @EndUserText.label: 'Storage Condition'
       @ObjectModel.text.association: '_StorCond'              
              mara.raube as StorageCondition, _StorCond,
       @EndUserText.label: 'Product Hierarchy'       
              mara.prdha as ProductHierarchy
        
       
}

BASIC/FACT

注意,在选择列表中,我们没有为字段添加任何语义(annotation),因为这是一个BASIC视图,而且我们在创建模型的FACT。语义annotation会在COMPOSITE视图中应用。

VDM可以根据需要由多个BASIC/FACT视图组成。

@AbapCatalog.sqlViewName: 'ZBFACDOCAXX'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Universal Journal Entry, Basic'
@VDM.viewType: #BASIC
@Analytics.dataCategory: #FACT 
@Analytics.dataExtraction.enabled: true
    
define view ZBF_ACDOCA_XX as select from acdoca 

{
       rbukrs as CompCode,
       gjahr  as FiscalYear,
       poper  as Period,
       racct  as GLAccount,
       matnr  as Material,
       werks  as Plant,
       
// UOMs - Currencies
       runit  as UOM,
       rhcur  as CCCurr,
       
// Measures
       msl    as Quantity,
       hsl    as AmtCC              
}

COMPOSITE/CUBE

@AbapCatalog.sqlViewName: 'ZCCACDOCAXX'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Universal Journal Entry, Composite'
@VDM.viewType: #COMPOSITE
@Analytics.dataCategory: #CUBE
@Analytics.dataExtraction.enabled: true

define view ZCC_ACDOCA_XX as select from ZBF_ACDOCA_XX 

association [0..1] to I_Material    as _Mat      on $projection.Material = _Mat.Material
association [0..1] to I_Plant       as _Plant    on $projection.Plant    = _Plant.Plant
association [0..1] to I_CompanyCode as _CompCode on $projection.CompCode = _CompCode.CompanyCode

{
      @ObjectModel.foreignKey.association: '_CompCode'
      CompCode, _CompCode,
      FiscalYear, 
      Period, 
      GLAccount, 
      @ObjectModel.foreignKey.association: '_Mat'
      Material, _Mat,
      @ObjectModel.foreignKey.association: '_Plant'
      Plant, _Plant,
      //UOMs - Currencies
      @Semantics.unitOfMeasure: true
      @EndUserText.label: 'Base UOM'
      UOM, 
      @Semantics.currencyCode: true
      @EndUserText.label: 'Comp. Code Curr.'
      CCCurr, 
//Measures 
      @DefaultAggregation: #SUM
      @EndUserText.label: 'Quantity'
      @Semantics.quantity.unitOfMeasure: 'UOM'
      Quantity, 
      @DefaultAggregation: #SUM
      @EndUserText.label: 'Amount CC'
      @Semantics.amount.currencyCode: 'CCCurr'
      AmtCC
}

CONSUMPTION

@AbapCatalog.sqlViewName: 'ZCCACDOCAXXQ001'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Universal Journal Entry, Query'
@VDM.viewType: #CONSUMPTION
@Analytics.query: true 
define view ZCC_ACDOCA_XX_Q001 as select from ZCC_ACDOCA_XX 

{
    //ZCC_ACDOCA_XX 
    @Consumption.filter: {mandatory: false, selectionType: #SINGLE, multipleSelections: true}
    CompCode, 
    FiscalYear, 
    Period, 
    GLAccount, 
    Material, 
    @AnalyticsDetails.query.display: #KEY_TEXT
    @AnalyticsDetails.query.axis: #ROWS  
    Plant, 
  
//UOMs - Currencies  
    UOM, 
    CCCurr, 
    
//Measures    
    Quantity, 
    AmtCC 

}

优势

  VDM的主要优势之一是只要构建一次即可在多种前端工具中消费:

  • BOBJ
    • WEBI
    • Analysis for Office
    • Crystal
    • OLAP
  • Lumira Discovery (even though it's being discontinued in favor of Analytics Cloud)
  • Analytics Cloud
  • ALV Grid
  • OData services
  • Fiori

  此外,因为CDS视图存在于应用层,我们可以通过PFCG借力于既有的ABAP安全模型。对于CDS视图安全,我们可以使用Data Control Language (DCL)来控制。有关DCL的更多信息,可以看以下文章:

  一旦你学会了如何用CDS视图建模,开发VDM的速度会变得很快,可以借此为用户提供快速、高效的报表解决方案。

性能

  关于性能,VDM在高容量高聚合的场景的表现是惊人的。我构建了一个采购订单视图,从header到计划行,有许多主数据的join。计划行表有大概2500万数据,数据时间跨越了8年。

  当运行没有过滤的汇总报表时,列上有3个度量而下钻时只有年度(8行,3列,24个数据点),报表在1-2秒内完成查询!

  现在,使用和上面相同的数据模型,当我运行一个非常详细的报表时,查询到计划行项目,获取许多不同的属性,下钻大概30行,获取整个月份的数据。这时报表大概花了10分钟来运行。为什么?因为它实时进行了我在模型中定义过的所有join和计算,处理上十分密集。

  上面的场景十分适合采用BW的持久化解决方案,它可以进行任何计算和数据连接。报表运行时,数据持久化为ADSO,可以简单地基于选择条件获取数据,不需要任何附加处理,预期的查询时间将短至亚秒级。

 

本文翻译自以下文章:

S/4 Embedded Analytics – The Virtual Data Model

S/4 HANA Embedded Analytics

参考文章:

VDM

 
 
 
posted @ 2018-07-10 15:40  氢氦  阅读(5842)  评论(0编辑  收藏  举报