背景
笔者在来唯品会之前主要的工作内容主要是依托于公司自研的bi低代码平台进行报表、图表开发工作,在此基础上做产品化的探索。因此在离线数仓建模和开发有过一些实践,也有一些思考,在此尝试做一点简要的梳理。
什么是数据仓库
首先先简单说明一下,什么是数据仓库。数据仓库是一个数据存储的集合,其创建目的是为了企业经营数据分析以及决策支持。数据仓库的输入是企业各个应用系统产生的数据,通过特定的范式的模型对企业数据进行筛选,整合和存储,再提供给数据应用。可以为企业提供bi能力,目的是更好的控制和指导企业的经营过程。 数仓的架构有Bill Inmon范式和Ralph Kimball范式,在以bi数据报表为最终应用的中小型数据项目上,通常采用Kimball范式作为开发指导模型,不过通常会加多ods层存储业务系统引入的数据,类似一种混合的架构。 Kimball范式
Inmon范式
分层设计
数据引入层(ODS):非结构化数据进行结构化处理,结构数据通常使用离线数据同步的方法全量或者增量同步业务系统的数据,为数据的转换加载做准备。 数据公共层(CDM):1,维度表(DIM),通过业务的梳理,建立一致性的数据分析维度。维度表的统一定义和管理往往是最终项目是否可控的重要因素。2,明细事实表(DWD),基于维度建模,复用关联计算,减少数据扫描。3,公共汇总表(DWS),通常在明细表的基础上进行汇总,构建统一口径的统计指标,建立宽表。 数据应用层(ADS):复杂的,个性化,定制化的计算指标。基于应用的宽表数据组装。
维度建模
如上面所说的,以bi应用出发的建模方式通常采用的Kimball范式,而其逻辑模型为星型模型或者雪花模型。鉴于复杂性控制的考虑,实际开发中我们往往使用星型模型。典型的星型模型的逻辑结构如下图,由一个主题表关联多个维度表,在sql层面通过不同的连接方式以及累加,半累加函数的使用在此基础上出数据,做多维分析。
低代码平台做什么?
基于维度模型,在报表和图表开发的场景中,可以设计ide通过拖拉拽的方式生成模型协议和报表协议。通过引擎解析报表协议元数据动态生成sql,获取数据。以下列出一个模型,协议,报表和动态生成的sql的简单例子。 假设有模型:然后有一个ide接管整个开发流程,ide可以生成主题的元数据,维度元数据,多维模型元数据。 现在的有个报表需求如下图。 那么实施人员就可以通过ide拖拉拽的方法拉取指标和维度,
假设生成这么一份报表协议(只是最简单的示例描述)。
{ “id”:xxx, “modelid”: 链接多维模型的id,可以拿到表和连接关系, “reporttype”: “linebar”, “rows”: [ { “code”: “xxx”, “dimid”:“链接维度表的元数据” “elementname”: “yearmonth”, “alias”: “年月” } ], “indexs”: [ { “code”: “xxx”, “factid”:“链接主题表的元数据” “elementname”: “index”, “aggregator”: “sum”, “alias”: “指标” } ] } ], “options”: {前端交互相关的参数协议,比如时间控件的定义}, “echartsoption”: {echarts图表相关的参数} } 然后在前端请求报表的时候,引擎通过解析报表协议,结合模型和主题维度等元数据以及本次请求前端的传参,动态生成本次请求的sql(基于postgres),类似
select
dim_date.yearmonth as 年月,
sum(fact.index) as 指标
from fact fact
left join dim_date dim_date on fact.date=dim_date.date
where to_char(dim_date.date,'yyyy')='2021'
group by dim_date.yearmonth
用这个sql取数,然后拼接返回数据的协议,前端渲染到echarts折线图组件中 这样一个流程,就实现了bi报表的低代码开发。
理想vs现实,数仓实践中踩坑以及思考
1,身处下游的痛苦 离线数仓不可能记录业务系统的所有的操作和操作结果,数据同步只能是周期性的同步数据的快照。如果业务系统出现类似ABA这种问题,这种情况在业务系统影响效果的扩散会导致数据在数据应用里逻辑无法自洽。而排查过程苦不堪言,最终往往帮忙揪出了业务系统藏得比较深的bug。因此业务系统的完善健壮往往是数据仓库能成功的关键因素。
2,olap数据库选型 之前公司数据库的选型用的postgres,号称最先进的开源数据库。从我入职唯品会之后用mysql的对比,还是可以感觉到postgres某些性能方面的强悍。在一些不大的项目上,pg可以撸平etl工作和olap分析。但是数据量一大,再用pg就是小马拉大车有点勉强了。并且在业务上经常遇到一种场景,就是计算指标的同比环比的情况。用上述多维模型和报表引擎这套东西很难直接处理,比如,业务系统同步过来的数据以某些维度看有本年数据但是没有上年数据,这个种数据缺失报表展示经常就无法自洽。而这种情况如果不手撸存储过程出报表那就只能在etl阶段用笛卡尔积先展开所有的维度值,然后再对应update相应的指标,就会导致表数据量膨胀得可怕,一个报表几分钟刷不出来。但是如果把模型拆成好几个,又失去了统一建模的意义。这个一直是个棘手的问题。
3,报表引擎能力边界以及无代码的思考 之前吐槽过平台报表引擎越来越复杂,用报表引擎拖拉拽方法配出一个能用的报表的复杂程度和心智负担不低于直接用sql自己撸一个,大佬说报表引擎并不是只是为了简化开发过程,也有帮助沉淀业务模型的作用。结合很久以前就和小伙伴讨论过,无代码平台如果是想包罗万象那最终的结果只能是搞出另一套图灵完备的语言。由此我有个思考,如果只把业务沉淀在静态的多维模型里面,而交互过程交给一个通用的报表引擎,我认为并不能在应对客户刁钻变化的需求和心智负担明显低于手写sql两个方面兼得。而作为平台开发者,认清自己的边界以及小心翼翼的探索针对特定领域能做哪些事情,是一个巨大的挑战。
|