高级元数据设计

阅读(5130) 标签: 高级元数据, lmd,

通过语义层小节的学习,相信已经对元数据文件的制作有了初步了解,其实,元数据中除了可以做一些常规的设置外,还可以做一些高级设置,比如智能识别外键分表等,本节将主要针对这些高级元数据设计做进一步介绍。

智能识别外键

有些表间存在着逻辑上的外键关系,但是程序员设计数据库的时候并没有实际定义,因此,从数据库读入物理表结构的时候,会缺少这些外键定义。

智能识别外键的功能,就是根据选中的主表(维表),智能地查找其它表中是否有字段数据类型、长度、值和选中主表的主键完全一致,且数据符合外键规范,没有定义外键的情况,如果有则列出来,用户根据实际情况进行选择确认,一旦被确认的,会自动加到外键定义中。

在连接数据源后,在菜单中可以选择执行智能识别外键

在窗口中选择主表,点击【确定】后,系统会智能匹配所选表的结构数据,从系统中选择出和所选表相匹配,且未设定外键的对象出来。

对系统自动识别出来的关系,可以进行人工审查,并进行干预和调整,以便最大限度的保证模型的正确性。点击【确认】可以确认使用一条映射,点击【删除】则不使用,调整后如下:

点击【确定】后,模型中会自动生成外键关系

知识点:

1) 对于设计规范的数据库,可直接使用导出的模型结构,建模工作量可以忽略不计。

2) 外键字段与引用表的主键字段,应该具有相同的数据类型以及数据宽度、数据精度等,这样才可以智能识别,否则只能手工指定。

 

层函数

通过使用层函数,可灵活定义多维度的层次结构,如时间维度的年、年月、日,地理维度的国家、省、市等,使用户能够在不同粒度上分析数据。这类层次结构在元数据编辑设计器中只需一次定义,即可在多处复用,极大提升了数据分析的灵活性。

在元数据定义中,当表间的外键关系设定之后,系统会根据外键设定中产生的维信息,自动生成维的相关定义。然后可以在元数据的维和层页面里,定义这几个维度间的计算关系。

 

当表中函数的参数为某个维度,且返回的维度与原维度不同时,该函数称为层函数通过定义维的各个层次关系,使用户能够在不同的粒度上观察数据。

对于层次结构的定义,通常有几个维度就定义几张表(或假表)。例如,地理维度可拆分为地区表、省表、城市表三张表,分别对应地区、省、市三个层级。业务表中的字段需与对应层级的表建立关联,比如:若业务表存储 “市” 级数据,字段需关联 “市表”;若存储 “地区” 级数据,字段需关联 “地区表”。

demo.lmd中的省、大区、市表为例,表结构及数据内容如下:

 

使用以上三个表定义层次:

:

:

大区:

说明:

1)层函数表达式可以使用DQL提供的标准函数,在层间计算式中用?表示源字段表。比如以下设置表示大区维大区字段的值可以由维的省字段通过表达式?/100计算而来:

定义好层结构后,就可以在DQL中直接使用定义中的任何结构,比如:

客户表“市”是个数值型字段,在客户表的外键定义中,我们将客户表的字段“市”与表的字段“市”建立外键关系,如下图:

这样,我们就可以在DQL中获得市的省、地区等信息了,如#,得到的省,#大区就得到了的地区:

DQL: SELECT 客户,客户名称,联系人姓名,联系人职务,,#省 省,#大区 大区 FROM 客户

 

DQL: SELECT count(客户) 客户数量 ON 大区 FROM 客户 BY #大区

 

DQL: SELECT count(客户) 客户数量 ON FROM 客户 BY #

 

假表

假表是一种虚拟的单字段无记录表,可以视为普通表来使用,主要用于在无实体表的场景下定义维度层次,如时间维度通常没有实体表,此时就可以通过假表实现。

demo.lmd中通过日、月、年三张假表定义的日期层次为例:

 

  

说明:

1)  系统已为日期维度预定义常用层函数

year

season

month

day

week

星期几,1表示星期天

yseason

带有年的季

ymonth

带有年的月

2) 层间计算式也可以理解为从细向粗计算。比如维,只能从日算出年,不能从年算出日。

3) 目标维可分别通过多个源维进行换算。比如维,可能是从日聚集到年,也可能从年月聚集到年,因此,对于维,就要定义两个层间计算式,分别从表的日期和表的年月计算而来。

接下来可以在DQL中直接使用定义定义好的日期层函数,如下例:

回款单表中回款日期是个日期类型,在回款单表的外键定义中,我们将回款单表的字段回款日期表的字段建立外键关系,如下图:

这样,我们就可以在DQL中获得回款日期的年、月等信息了,如回款日期#年,得到回款日期的年份,回款日期#月就得到了回款日期的年月

DQL: SELECT 客户,回款单,回款日期,回款日期# ,回款日期# ,金额,雇员 FROM 回款单

 

DQL: SELECT 回款单.sum(金额) 总金额 ON FROM 回款单 by 回款日期#

 

DQL: SELECT 回款单.sum(金额) 总金额 ON FROM 回款单 by 回款日期#

 

维名

在讲外键的时候,我们说到,表的外键必将指向一个维。因此,只要为某些字段定义了外键,DQL就会自动把外键最终指向的.关键字段作为维存储在维定义里,一般情况不需要单独去定义

但是,表.关键字段这么长的名称作为维名很不方便,写DQL的时候显得太长,所以,可以在维定义里修改维名,使之更短更容易记忆。

格式化表达式:用于日期维,可以把字符串按照表达式转换成维值,其中用?1?2...引用子串参数。表达式支持DQL提供的标准函数,返回结果需是字段对应的类型。汉语查询时,可将字符串转换成该维度的值。

正则表达式:用于将字符串识别成常数。如果字符串和正则表达式匹配,则会将字符串当成常量。汉语查询时,可将匹配成功的字符串当成该维度的值。

 

DQL

-  SELECT 客户ID.客户名称,回款单.SUM(金额)

-  ON 客户.客户ID

-  FROM 回款单BY 客户ID

如上图定义了维名后,就可以写成

-  SELECT 客户ID.客户名称,回款单.SUM(金额)

-  ON 客户

-  FROM 回款单BY 客户ID

基础表与汇总表

很多业务系统的数据量巨大,直接从基础业务表进行查询汇总会非常慢,因此数据库里往往存在一些已经造好的历史汇总表。

对于用户来说,当他进行查询时需要知道有哪些历史汇总表存在的难度比较大,尤其是当存在多级汇总表的时候,要能够恰当选择其中一个汇总表难度更大了。

因此如果某张表是历史汇总表,那么可以在这张表上定义基础表属性,定义其从哪一张基础表汇总而来。当用户的DQL基于基础表进行分组汇总时,DQL元数据层会智能寻找汇总表,看哪个汇总表和DQL的汇总级别最接近,然后智能地把DQL解析成从这个汇总表查出。汇总表和基础表是相对的概念,表A是表B的基础表,则表B是表A的汇总表;在定义了基础表属性后,这个历史汇总表会自动加入其基础表的汇总表中

举例来说,有一个基于日期的基础表,数据库中存在按月汇总、按年汇总的两张汇总表。当用户的查询DQL是聚合到季这一层时,系统会自动从月汇总表里查出;当聚合到年时,会自动从年汇总表里查出。

汇总表和基础表之间是多对多的关系。

举例

现有支付单,支付月汇总两张表。支付月汇总表数据是从“支付单”表汇总而来,那么可以定义如下:

上图中的字段名是“支付月汇总”表的字段名,广义外键或表达式是指基于基础表的计算表达式,可以把上述定义理解为这样的DQL

-  SELECT

-   支付单.SUM(支付金额) 支付总额

-   ON 年月

-  FROM

-  支付单

-  BY 支付日期#年月

此时,如果需要基于支付单,进行年汇总,即下面的DQL

-  SELECT

-    支付单.SUM(支付金额) 支付总额

-    ON

-  FROM

-    支付单

-  BY 支付日期#

DQL元数据层会自动从已有的支付月汇总的数据中进一步汇总,即执行以下SQLSELECT INT(T1_1_1.年月/100) ,SUM(T1_1_1.支付总额) 支付总额 FROM 支付供应商月汇总 T1_1_1 GROUP BY INT(T1_1_1.年月/100),通过对基础表的设定,可以充分利用事先汇总完成的数据,以提高效率。

 

知识点:

1) 定义基础表功能,可以简化业务视图,降低用户对业务系统的学习难度,用户只需要记住基础表即可,不需要记忆汇总表。

2) 在定义基础表功能时,其中的字段名,必须包括主表的所有关键字段,如上图中的年月为支付月汇总主键,必须定义广义外键或表达式。计算字段可以全写,或只写一个。

3) 在上述定义中,我们定义年月的广义外键或表达式为支付日期#年月,如果层函数或者假表中出现错误或异常,也会导致系统不能自动找到汇总表。

4) 当基础表中有多个汇总表可用时,会通过对表中记录数的设置选择记录数少的使用,记录数相同或都为空时取第一个符合条件的汇总表。

子表

在元数据中,当A表中有多个主键时,对部分主键字段添加外键后,在外键对应的主表中会自动将A表做为子表列出。子表外键必须关联主表主键字段。

部分主键字段构成外键指向的表是主表;单字段主键的层函数的维表是主表;主表的主表是主表;同维表的主表是主表;主表的同维表是主表。

例如:

客户ID客户表中的主键字段,回款单中客户ID和回款单ID为主键字段,回款单的客户ID外键指向客户表的客户ID

回款单中外键设置如下:

客户表中会自动添加子表回款单,子表外键为对应主表主键的外键字段,如下:

分表

在数据库中,有时,数据会分开存储在多个数据结构完全相同的表中,如分年度存储的销售数据、分部门存储的员工资料、分地区存储的客户信息等等。在数据查询与分析时,往往需要将这些表中的数据联合起来,比如查询历年销售数据、查询所有部门的员工资料或者查询全部客户信息等,此时,可以通过在DQL元数据文件中,设定分表

建立分表,可以直接点击【增加分表】按钮执行,也可以在菜单栏中选择编辑 - 增加分表,或者使用快捷键Ctrl+B

选择后,可以选择组成分表的各个物理表来源:

物理表可以在当前数据源的数据库表中选择,也可以在元数据表中选择,选择的物理表必须具有相同的数据结构:

选定分表的数据表来源后,可以为分表命名,字段定义会自动生成:

与元数据中的普通表定义不同,分表中还需定义分区属性,根据指定的分段字段,设定分表中的分段列表。分段字段需是维字段,而且,分表中的各个分区表的分段字段的值需要是严格单调的,这样才可以根据分段字段的设定,在查询时,合理将分表拆分。设定分段列表时,每个物理表作为一个分区,由小到大设定段界,设定段界的值将包含在分区内,如下面的设置:

图中的设定,相当于设定分区订单2011 中,分段字段订单编号<=10554;最后的一个分区订单2012 的段界可以为空白,此时最后一个分区无上限。

在查询时,分表的使用和元数据中其它表的DQL语法相同,比如:

SELECT * FROM订单总表

DQL元数据层会自动将分表中的各个物理表联合访问,相当于执行:

SELECT T1_1.订单编号 订单ID FROM (SELECT * from 订单2011 UNION ALL SELECT * from 订单2012) T1_1

那么,分表中,分区的设定有什么意义呢?在执行有条件的查询时,有时候查询的数据并非来源于分表中所有的物理表,此时如果筛选条件是分段字段,在DQL元数据文件中就可以根据分段列表中的段界设定,寻找到数据来源于哪个或者哪些物理表,从数据查询时只访问相关的数据库。

如:SELECT * FROM 订单总表 WHERE 订单编号<10250

DQL会解析为:SELECT T1_1.订单ID 订单ID FROM (SELECT * from 订单2011) T1_1 WHERE T1_1.订单ID<10250

如:SELECT * FROM 订单总表 WHERE 订单ID in (10620,10630,10640)

DQL会解析为:SELECT T1_1.订单编号 订单ID FROM (SELECT * from 订单2012) T1_1 WHERE T1_1.订单ID IN (10620,10630,10640)