2021-数据产品小 Lee-数据仓库基础

数据仓库基础

维度模型

什么是模型,什么是建模?

什么是模型?作为数据行业从业者,如果你从来没有思考过这个问题,你一定要看下去。先看一个例子:

2021 年 3 月 6 日,小明到楼下【行家】便利店买吃的,来来回回逛了几圈,虽然很饿,但又想减肥,最终拿了 1 个【柯德吉】人造肉汉堡。准备付账的时候,收银员跟他说,最近搞活动,加 4 块可以选一瓶原价 8 块的【卡石】酸奶。小明觉得很划算,于是去拿了酸奶,一共付了 12 块。

上面的这段文字,就是模型。先看看百度百科给出的模型定义:

模型,是指通过主观意识借助实体或者虚拟表现构成客观阐述形态结构的一种表达目的的物件(物件并不等于物体,不局限于实体与虚拟)

简单来说,模型是映射 “事实” 的东西,构建这个东西的动作就叫做建模。上述的例子,是一种“文字模型”。而且,这个模型还可以补充更多细节,比如,采用什么方式付款、支付了多少钱。为了表达更加简洁,我们可以省略更多的信息,只记录关键信息:

2021 年 3 月 6 日,小明买了,一个 柯德吉 牌人造肉汉堡,一瓶 卡石 牌酸奶(共计 ¥ 12)。

范式模型,为了更好地记录和更新

计算机的出现,也诞生了新的语言,我们也顺理成章地开始用新语言去建模。假设这个便利店用了现成的 ERP、CRM 系统,这些系统设计好了模型,数据会填充成如下的样子:

1)订单表

订单表

2)订单详情表

订单详情表

3)商品详情表

商品详情表

数据量不大,分析人员写 SQL 直接对范式模型进行查询,算账分析无所不能,小几十万数据,速度完全 OK。

维度模型,为分析而生

范式模型很好地解决了快速记录和节约存储空间。但事物都有两面性,当数据量大的时候,从范式模型中查询取数,就比较慢了。但数据量一大,就顶不住了。人类社会,但凡出现问题,总会天降猛士。Innon 和 Kimball 等人提出来新方案:为数据分析设计一套新模型。

范式模型主要解决数据的插入和更新,维护一致性等问题,维度模型则解决大数据场景分析的问题,这两者也就是所谓的 OLTP 和 OLAP 。通过一个荒诞的例子来理解两者的区别:

你家是个大家族,七大姑八大姨,平时需要打电话联系。 范式建模:每个人只存自己同辈人以及各自子女的联系方式。如果叔叔想找侄子/侄女(你),只能通过你爸爸。 维度建模:所有的亲戚联系方式都写到了一个家庭通讯录上,想找人,直接找通讯录。

这个例子现实生活不存在,主要想帮助大家理解两种模型的差异:

1、范式模型为了应对数据频繁变更的场景,数据存得零散。为了保证数据的一致性,还要符合一定的规范,我们常见的是三范式(3NF)。 2、维度模型会将数据冗余,把一些相关的数据存到一起,方便快速查询取数。维度模型的出现,就是为了解决大数据量导致的查询慢的问题。

维度建模的四大要素

数据仓库领域的经典著作《维度建模工具箱》中,Kimball 定义了经典的维度建模的四步曲,:选定业务过程、声明粒度、确定维度、构建事实。

1)业务过程

很多数据仓库书籍都给出了业务过程的通用定义:业务过程是企业活动中的事件,如下单、支付、退款都是业务过程,业务过程是一个不可拆分的行为事件。看完定义,我们就会犯难了,什么是企业活动中的事件?打开手机付款,选择支付宝和微信,这些操作算不算业务过程?

这里,我们真得咬文嚼字,回归场景。交易的场景,有 2 个参与方:消费者和便利店。便利店作为企业,如果它关心的结果只是消费者买了什么,买了多少,那消费者选择支付方式的事件,它完全不管,也不用记录。

但如果用户只开通了微信支付,没开通支付宝,因为支付问题导致没法成交,那企业肯定也会关心选择支付方式这个事件以及其结果。业务过程,是不可拆分的事件,而且是基于分析目标进行选定的。理解一个词,不能脱离情景,多尝试将自己置于企业经营的情景下。

企业里每天都有各种事情,而作为管理者的我们,最核心的关注点是什么?是从收益、成本出发,价值链条上最具影响力的事情或者事件。

2)粒度

理解粒度,其实很简单:干什么样的事情,会新增一条记录。小乐支付了一笔,系统会新增一条支付记录,当我们要统计分析交易的订单数时,订单是最细的粒度。而这笔交易中,包含了两个商品,当我们要分析所有订单卖出的商品数,每个商品则变成了最细粒度。

3)维度

维度,就是我们要进行分析的角度。比如,在便利店场景中,一天的经营结束了,可以按品牌的维度分析,各个品牌的酸奶销售量;可以按日期维度分析,我们可以知道,周一到周日,每天的交易额如何。

某天,当我们发现交易数据发生异常的时候,我们可以按照品牌、日期等维度进行分析,逐个排查,直到找到根本的原因。

4)事实

广义地来说,所有被记录下来的事情,都是事实。而维度建模中,对事实进行了细分,事实包含 2 类属性:维度、度量。维度就是上文所说的各个角度的数据,而度量,则通常是数值型的。举个例子,我们描述一个长方形,但是没描述它具体多长、多宽,其他人是没法确定这个长方形具体多大的。

如果只有补充上它对应的维度和度量,人们才能理解。比如,长 4cm,宽 3cm。长、宽是维度,4 米、3 米则是对应维度上的度量。事实,就是描述客观事物的所有核心信息的所有数据的集合。

理解业务过程

很多数据仓库书籍都给出了业务过程的通用定义:业务过程是企业活动中的事件,如下单、支付、退款都是业务过程,业务过程是一个不可拆分的行为事件。

如何理解企业活动

同一件事情,按照不同的对象,会有两种描述。这样说很抽象,举个例子:A 公司向 B 公司进了一批货。

  • A 公司的记录是:采购单。
  • B 公司的记录是:销售单。

业务过程,是有对象主体的,其主体就是:数据仓库索要服务的对象。这个时候,我们要确定一个分析的层次,或者叫做,抽象的粒度。我们只分析企业这个层级的事情,而不分析员工级别的事情。

如何理解不可拆分

这还是要基于层级去说。假如某天有很多消费者在商店里面买了东西,便利店作为企业,如果它关心的结果只是消费者买了什么,买了多少。那消费者选择支付方式的事件,它完全不管,也不用记录。在便利店这个层级,只关心交易结果,不用关心交易过程中的具体支付方式。

业务过程,是不可拆分的事件,基于分析目标进行选定的。但如果用户只开通了微信支付,没开通支付宝,因为支付问题导致没法成交,那企业肯定也会关心选择支付方式这个事件以及其结果。

理解一个词,不能脱离情景,多尝试将自己置于企业经营的情景下。企业里每天都有各种事情,而作为管理者的我们,最核心的关注点是什么?企业是从收益、成本出发,关注价值链条上最具影响力的事情或者事件。

整明白粒度

选定了分析的过程,紧接着就要声明粒度。看到书里这么说,我当时的反应是:为什么?粒度是什么?普通场景里,粒度可以理解为一个东西的大小。比如,钻石要区分颗粒度,大小不同的钻石,价格不一。而在数据分析的语境里,粒度则意味着分析的范围,分析的细致程度。

举两个例子。

  • 系统的注册总人数,可以按照国家、省份来统计,这是地域层面上的不同统计粒度。
  • 系统的活跃用户数,可以按天、按周统计登录人数,这是时间层面上不同的统计粒度。

从数据表的角度来看,粒度则解释着什么情况下增加一条记录。

  • 按国家统计用户数,中国只会有一条记录,按省统计,中国则会有 34 条记录。
  • 按周统计活跃用户,一年只会有 52 行记录,按天统计,一年则有 365 或 366 条记录。

通过实战理解粒度

公司出了新 APP,老板很关心新 APP 的用户活跃程度,于是,用户端产品经理希望做个面板,看每天有多少人登录。同时,他提了另一个需求,他希望能支持统计两个日期区间内的登录人数(两个日期是变化的)。通过例子理解:某个活动发布后,要查看不同时间区间内的累积活跃用户数,比如 1-2 号,3-5 号,以便及时调整促活的策略。

首先,选定业务过程。这个一目了然,自然就是用户登录过程。其次,声明粒度。这里用户方希望按照不同的日期统计累积人数,那粒度是天。然后,是确定维度。这个例子里,因为要按照日期分析,最主要的维度是日期(为了简单,例子里就就先不考虑其他维度了),日期维度表设计如下:

日期维度表

最后,设计事实表,用户登录事实表(fact_loign)设计如下:

事实表

维度模型搞不定,是粒度理解不到位

构建模型,最终都是为了查出对应的指标和结果,所以维度模型通常都会跟标准的指标系统配套来使用。当我们按照标准套路,进入指标设计阶段,问题就会慢慢浮出水面了。基于事实表模型,我们很容易设计原子指标【登录人数】,其计算逻辑为:

count(fact_login.user_id)

进而,我们也能设计出衍生指标【日期_登录人数】,其口径为:

select distinct count(fact_login.user_id)
from fact_login
left join dim_date on date.date_key = fact_login.login_date
group by dim_date.date_key

从衍生指标这里,就能发现问题了。你会发现,group by 后的结果,是按照每天进行去重的。最终的结果,只能是统计每天范围内的累积登录人数。用户的期望是,统计某个时间区间内的累积登录人数,这个需求维度模型产生的指标没法满足。如果事实表的真实数据如下:

事实表

基于维度模型,系统可以生成这样的汇总表:

汇总表

但系统无法生成如下汇总表:

汇总表

粒度是搞清问题的关键

让我们回归到真实场景里:登录成功,这个事件发生在一瞬间。常见的时间计量单位有年、月、天、小时、分钟、秒、毫秒、微秒等等。而系统记录某个操作,常见的记录粒度是秒。比如, 2021 年 6 月 27 号 14 : 00 : 00,小明登录了系统。如果按照秒去统计登录人数,则完全不用考虑去重,因为小明在这个粒度的计量单位里,只能登录一次。

但秒级别的统计粒度,太细了。业务方希望从更加宏观的角度去统计和分析,例子里面,是以天为单位去统计。那这个时候,统计就要升粒度了,并且,要去重。此时,系统也是可以按照天的粒度进行去重统计的。再看看实际需求时,统计的时间区间是不固定的。即,业务方可能今天想统计 1 号到 2 号的登录人数,明天想统计 3 号到 5 号的登录人数。

粒度不固定:1-2 号,间隔时间是 1 天,3-5 号,间隔时间则是 2 天。维度建模中,声明粒度就是要把粒度的大小定下来。不管是什么维度,都要提前把粒度定下来,这样才能实现累计去重。从技术实现的角度来看,如果查询的粒度,是一个变量,而不是一个固定值,没法提前计算,只能临时用明细表算,这就叫做即席查询。

所以,这个需求中,维度建模只能解决前面部分的需求:按照天去重统计每天登录人数。而变化区间的去重统计,只能即席查询了。

搞懂维度

维度是什么

1)阿里 dataphin 产品简介-基本概念是这样介绍维度:

人们观察事物的角度,是指一种视角,是确定事物的多方位、多角度、多层次的条件和概念。

2)华为 DGC 产品介绍-基本概念如此介绍维度:

维度是用于观察和分析业务数据的视角,支撑对数据汇聚、钻取、切片分析,用于 SQL 中的 Group by 条件。多数维度具有层级结构,如:地理维度、时间维度。

3)再看看《数据仓库工具箱》怎么说的:

维度能提供围绕某一业务过程所涉及的 “谁、什么、何处、何时、为什么、如何”等背景。维度表包含 BI 应用所需要的用于过滤及分类事实的描述性属性。牢牢掌握事实表的粒度,就能够将所有可能存在的维度区分开。当与给定事实表进行关联时,任何情况下都应该使维度保持单一值。

4)再看《阿里巴巴大数据之路》怎么说的:

维度是维度建模的基础和灵魂。在维度建模中,将度量称为 “事实” 将环境描述为 “维度” ,维度是用于分析事实所需要的多样环境。 例如,在分析交易过程时,可以通过买家、卖家、商品和时间等维度描述交易发生的环境。 维度所包含的表示维度的列,称为维度属性。维度属性是查询约束条件、分组和报表标签生成的基本来源,是数据易用性的关键。 维度的作用一般是查询约束、分类汇总以及排序。

维度和粒度的关系

1)维度有层级结构,不同层级对应不同的粒度。

地理维度有不同的层级:国家、省/自治州/直辖市、市、县,时间维度也有不同的层级和粒度:年度、季度、月度、星期、天等。正如有了要描述的事情,确定了粒度,再去找对应的维度。比如,订单系统,会记录下单的时间信息,时间维度上,粒度会细到秒。学籍系统,学生户籍信息中,要填入地区维度的信息,粒度要细化到省市。

2)维度的组合越多,粒度越细细

客观的世界,是多维的。描述一个客观事物,维度(通常配合相应的度量)越多,粒度越细。比如一个箱子,我们可以描述其长宽高,还可以描述颜色。不同描述维度组合越多,粒度越细,描述也越细致。

3)随着事物的变化,描述的维度可以增加

一个箱子会经历生产、运输、送货上门等环节,从产地送达到顾客手中。箱子被生产出来后,没有品牌、产地属性,或者说属性值为空。未经历运输过程的箱子,没有快递公司、配送员属性。但是人们可以赋予它这些维度,并且填入维度值。维度是基于人类描述客观事物的需要,被创造来的。

4)有的维度,没有直接的数字度量

从客观唯物主义的角度来说,某个实体的存在,长、宽、高这种比较客观的维度属性,是有确定值的。但某些主观的东西,也是需要被描述的。比如,人的帅气程度。我们就简单分两类:很帅、一般。这种主观的维度,没有绝对精确的度量值,无法直接和数字划上等号。

但聪明的我们依然可以定性、定量地测算进而描述。比如搞投票,得分超过 90 为很帅,60-90 为一般。但这种方式,只能估算,没有四海皆准的定值,不同的人群,投票结果不同。

两个有意思的维度问题

维度的角色

维度模型里,很多人不理解什么是维度角色。包括最开始的我自己。

维度角色

淘宝的业务过程大家应该很熟悉,涉及 4 个关键步骤:买家下单、买家付款、卖家发货、买家确认收货。每个过程,都会涉及一个对应的时间,即下单时间、支付时间、发货时间、确认收货时间。

如果只分析其中的一个业务过程,比如买家下单,那只需要一个时间字段即可。但是分析完整四个过程时,如果还只有一个时间字段,那如何区分其具体含义呢?到底是下单还是支付时间,搞不清楚。

只有一个字段,肯定不够。那必然要有 4 个时间字段。而且我们会给不同的命名,下单、支付、发货、确认收货作为时间的前缀。这样一来,咱们看的人是能理解各个数字的含义了。但不仅如此,还得让计算机系统也理解。所以,要弄一个 “维度角色”的字段来标识,以便计算机能理解。

维度角色 SQL

下一页