《大数据之路:阿里巴巴大数据实践》系列丛书

 第1章 总述

第1篇 数据技术篇
 第2章 日志釆集
 第3章 数据同步
 第4章 离线数据开发
 第5章 实时技术
 第6章 数据服务
 第7章 数据挖掘
第2篇 数据模型篇
 第8章 大数据领域建模综述
 第9章 阿里巴巴数据整合及管理体系
 第10章 维度设计
 第11章事实表设计
第3篇数据管理篇
 第12章 元数据
 第13章 计算管理
 第14章 存储和成本管理
 第15章 数据质量
第4篇数据应用篇
 第16章 数据应用


文章目录

  • 《大数据之路:阿里巴巴大数据实践》系列丛书
  • 第10章 维度设计
    • 10.1 维度设计基础
      • 10.1.1 维度的基本概念
      • 10.1.2 维度的基本设计方法
      • 10.1.3 维度的层次结构
      • 10.1.4 规范化和反规范化
      • 10.1.5 一致性维度和交叉探查
    • 10.2 维度设计高级主题
      • 10.2.1 维度整合
      • 10.2.2 水平拆分
      • 10.2.3 垂直拆分
      • 10.2.4 历史归档
    • 10.3 维度变化
      • 10.3.1 缓慢变化维
      • 10.3.2 快照维表
      • 10.3.3 极限存储
      • 10.3.4 微型维度
    • 10.4特殊维度
      • 10.4.1 递归层次
      • 10.4.2 行为维度
      • 10.4.3 多值维度
      • 10.4.4 多值属性
      • 10.4.5 杂项维度

第10章 维度设计

10.1 维度设计基础

10.1.1 维度的基本概念

  维度是维度建模的基础和灵魂。在维度建模中,将度量称为“事实”, 将环境描述为“维度”,维度是用于分析事实所需要的多样环境。例如, 在分析交易过程时,可以通过买家、卖家、商品和时间等维度描述交易 发生的环境。
  维度所包含的表示维度的列,称为维度属性。维度属性是查询约束 条件、分组和报表标签生成的基本来源,是数据易用性的关键。例如, 在查询请求中,获取某类目的商品、正常状态的商品等,是通过约束商 品类目属性和商品状态属性来实现的;统计淘宝不同商品类目的每日成 交金额,是通过商品维度的类目属性进行分组的;我们在报表中看到的 类目、BC类型(B指天猫,C指集市)等,都是维度属性。所以维度 的作用一般是查询约束、分类汇总以及排序等。
  如何获取维度或维度属性?如上面所提到的,一方面,可以在报表 中获取;另一方面,可以在和业务人员的交谈中发现维度或维度属性。 因为它们经常出现在查询或报表请求中的“按照”(by)语句内。例如, 用户要“按照”月份和产品来查看销售情况,那么用来描述其业务的自 然方法应该作为维度或维度属性包括在维度模型中。
  维度使用主键标识其唯一性,主键也是确保与之相连的任何事实表 之间存在引用完整性的基础。主键有两种:代理键和自然键,它们都是 用于标识某维度的具体值。但代理键是不具有业务含义的键,一般用于 处理缓慢变化维;自然键是具有业务含义的键。比如商品,在ETL过 程中,对于商品维表的每一行,可以生成一个唯一的代理键与之对应; 商品本身的自然键可能是商品ID等。其实对于前台应用系统来说,商 品ID是代理键;而对于数据仓库系统来说,商品ID则属于自然键。

10.1.2 维度的基本设计方法

  维度的设计过程就是确定维度属性的过程,如何生成维度属性,以及所生成的维度属性的优劣,决定了维度使用的方便性,成为数据仓库易用性的关键。正如Kimball所说的,数据仓库的能力直接与维度属性的质量和深度成正比。
  下面以淘宝的商品维度为例对维度设计方法进行详细说明。
  第一步:选择维度或新建维度。作为维度建模的核心,在企业级数据仓库中必须保证维度的唯一性。以淘宝商品维度为例,有且只允许有 一个维度定义。
  第二步:确定主维表。此处的主维表一般是ODS表,直接与业务 系统同步。以淘宝商品维度为例,s_auction_auctions是与前台商品中心系统同步的商品表,此表即是主维表。
  第三步:确定相关维表。数据仓库是业务源系统的数据整合,不同业务系统或者同一业务系统中的表之间存在关联性。根据对业务的梳 理,确定哪些表和主维表存在关联关系,并选择其中的某些表用于生成 维度属性。以淘宝商品维度为例,根据对业务逻辑的梳理,可以得到商品与类目、SPU、卖家、店铺等维度存在关联关系。
  第四步:确定维度属性。本步骤主要包括两个阶段,其中第一个阶 段是从主维表中选择维度属性或生成新的维度属性;第二个阶段是从相 关维表中选择维度属性或生成新的维度属性。以淘宝商品维度为例,从 主维表(s_auction_auctions)和类目、SPU、卖家、店铺等相关维表中 选择维度属性或生成新的维度属性。
  确定维度属性的几点提示:
(1)尽可能生成丰富的维度属性
  比如淘宝商品维度有近百个维度属性,为下游的数据统计、分析、 探查提供了良好的基础。
(2)尽可能多地给出包括一些富有意义的文字性描述
  属性不应该是编码,而应该是真正的文字。在阿里巴巴维度建模中, 一般是编码和文字同时存在,比如商品维度中的商品ID和商品标题、 类目ID和类目名称等。1D一般用于不同表之间的关联,而名称一般用 于报表标签。
(3)区分数值型属性和事实
  数值型字段是作为事实还是维度属性,可以参考字段的一般用途。 如果通常用于查询约束条件或分组统计,则是作为维度属性;如果通常 用于参与度量的计算,则是作为事实。比如商品价格,可以用于查询约 束条件或统计价格区间的商品数量,此时是作为维度属性使用的;也可 以用于统计某类目下商品的平均价格,此时是作为事实使用的。另外, 如果数值型字段是离散值,则作为维度属性存在的可能性较大;如果数 值型字段是连续值,则作为度量存在的可能性较大,但并不绝对,需要 同时参考字段的具体用途。
(4)尽量沉淀出通用的维度属性
  有些维度属性获取需要进行比较复杂的逻辑处理,有些需要通过多 表关联得到,或者通过单表的不同字段混合处理得到,或者通过对单表 的某个字段进行解析得到。此时,需要将尽可能多的通用的维度属性进 行沉淀。一方面,可以提高下游使用的方便性,减少复杂度;另一方面, 可以避免下游使用解析时由于各自逻辑不同而导致口径不一致。例如, 淘宝商品的property字段,使用key:value方式存储多个商品属性。商 品品牌就存存储在此字段中,而商品品牌是重要的分组统计和查询约束 的条件,所以需要将品牌解析出来,作为品牌属性存在。例如,商品是 否在线,即在淘宝网站是否可以查看到此商品,是重要的查询约束的条 件,但是无法直接获取,需要进行加工,加工逻辑是:商品状态为0和 1且商品上架时间小于或等于当前时间,则是在线商品;否则是非在线 商品。所以需要封装商品是否在线的逻辑作为一个单独的属性字段。

10.1.3 维度的层次结构

  维度中的一些描述属性以层次方式或一对多的方式相互关联,可以 被理解为包含连续主从关系的属性层次。层次的最底层代表维度中描述 最低级别的详细信息,最高层代表最高级别的概要信息。维度常常有多 个这样的嵌入式层次结构。比如淘宝商品维度,有卖家、类目、品牌等。 商品属于类目,类目属于行业,其中类目的最低级别是叶子类目,叶子 类目属于二级类目,二级类目属于一级类目。
  在属性的层次结构中进行钻取是数据钻取的方法之一。关于钻取的 定义,这里不做介绍,读者可以参考相关书籍。下面通过具体的例子, 看看如何在层次结构中进行钻取。
  假设已有一个淘宝交易订单,创建事实表。现在统计2015年“双 11”的下单GMV,得到一行记录;沿着层次向下钻取,添加行业,得 到行业实例个数的记录数;继续沿着层次向下钻取,添加一级类目,得 到一级类目实例个数的记录数。可以看到,通过向报表中添加连续的维 度细节级别,实现在层次结构中进行钻取。

  • 最高层次的统计,如表10.1所示。

  • 钻取至行业层次,统计如表10.2所示。

  • 钻取至一级类目层次,统计如表10.3所示。

      类目、行业、品牌等属性层次是被实例化为多个维度,还是作为维 度属性存在于商品维度中?如何设计,我们在下一节中详细讨论。

10.1.4 规范化和反规范化

  当属性层次被实例化为一系列维度,而不是单一的维度时,被称为 雪花模式。大多数联机事务处理系统(OLTP)的底层数据结构在设计 时釆用此种规范化技术,通过规范化处理将重复属性移至其自身所属的 表中,删除冗余数据。
  这种方法用在OLTP系统中可以有效避免数据冗余导致的不一致 性。比如在OLTP系统中,存在商品表和类目表,且商品表中有冗余的类目表的属性字段,假设对某类目进行更新,则必须更新商品表和类目 表,且由于商品和类目是一对多的关系,商品表可能每次需要更新几十 万甚至上百万条记录,这是不合理的。而对于联机分析处理系统(OLAP) 来说,数据是稳定的,不存在OLTP系统中所存在的问题。
  对于淘系商品维度,如果釆用雪花模式进行规范化处理,将表现为 如图10.1所示的形式。

  将维度的属性层次合并到单个维度中的操作称为反规范化。分析系 统的主要目的是用于数据分析和统计,如何更方便用户进行统计分析决 定了分析系统的优劣。釆用雪花模式,用户在统计分析的过程中需要大 量的关联操作,使用复杂度高,同时查询性能很差;而采用反规范化处 理,则方便、易用且性能好。
  对于淘宝商品维度,如果釆用反规范化处理,将表现为如图10.2 所示的形式。
  如上所述,从用户角度来看简化了模型,并且使数据库查询优化器 的连接路径比完全规范化的模型简化许多。反规范化的维度仍包含与规 范化模型同样的信息和关系,从分析角度来看,没有丢失任何信息,但 复杂性降低了。

釆用雪花模式,除了可以节约一部分存储外,对于OLAP系统来说 没有其他效用。而现阶段存储的成本非常低。出于易用性和性能的考虑, 维表一般是很不规范化的。在实际应用中,几乎总是使用维表的空间来 换取简明性和查询性能。

10.1.5 一致性维度和交叉探查

  构建企业级数据仓库不可能一蹴而就,一般采用迭代式的构建过 程。而单独构建存在的问题是形成独立型数据集市,导致严重的不一致 性0 Kimball的数据仓库总线架构提供了一种分解企业级数据仓库规划任 务的合理方法,通过构建企业范围内一致性维度和事实来构建总线架构。
  数据仓库总线架构的重要基石之一就是一致性维度。在针对不同数 据域进行迭代构建或并行构建时,存在很多需求是对于不同数据域的业 务过程或者同一数据域的不同业务过程合并在一起观察。比如对于日志 数据域,统计了商品维度的最近一天的PV和UV;对于交易数据域, 统计了商品维度的最近一天的下单GMV。现在将不同数据域的商品的 事实合并在一起进行数据探查,如计算转化率等,称为交叉探查。
  如果不同数据域的计算过程使用的维度不一致,就会导致交叉探查 存在问题。当存在重复的维度,但维度属性或维度属性的值不一致时, 会导致交叉探查无法进行或交叉探查结果错误。接上个例子,假设对于 日志数据域,统计使用的是商品维度1;对于交易数据域,统计使用的 是商品维度2。商品维度1包含维度属性BC类型,而商品维度2无此属性,则无法在BC类型上进行交叉探查,商品维度1的商品上架时间 这一维度属性时间格式是yyyy-MM-dd HH:mm:ss,商品维度2的商品 上架时间这一维度属性时间格式是UNIX timestamp,进行交叉探查时 如果需要根据商品上架时间做限制,则复杂性较高;商品维度1不包含 阿里旅行的商品,商品维度2包含全部的淘系商品,交叉探查也无法进 行。还有很多种形式的不一致,这里不再一一列举,但基本可以划分为 维度格式和内容不一致两种类型。
  上面对维度不一致性进行了详细分析,下面总结维度一致性的几种 表现形式。

  • 共享维表。比如在阿里巴巴的数据仓库中,商品、卖家、买家、 类目等维度有且只有一个。所以基于这些公共维度进行的交叉探 查不会存在任何问题。
  • 一致性上卷,其中一个维度的维度属性是另一个维度的维度属性 的子集,且两个维度的公共维度属性结构和内容相同。比如在阿 里巴巴的商品体系中,有商品维度和类目维度,其中类目维度的 维度属性是商品维度的维度属性的子集,且有相同的维度属性和 维度属性值。这样基于类目维度进行不同业务过程的交叉探查也 不会存在任何问题。
  • 交叉属性,两个维度具有部分相同的维度属性。比如在商品维度 中具有类目属性,在卖家维度中具有主营类目属性,两个维度具 有相同的类目属性,则可以在相同的类目属性上进行不同业务过 程的交叉探查。

10.2 维度设计高级主题

10.2.1 维度整合

  我们先来看数据仓库的定义:数据仓库是一个面向主题的、集成的、 非易失的且随时间变化的数据集合,用来支持管理人员的决策。其中集成是数据仓库的四个特性中最重要的一个。
数据仓库的重要数据来源是大量的、分散的面向应用的操作型环 境。不同的应用在设计过程中,可以自由决策,主要满足本应用的需求, 很少会考虑和其他系统进行数据集成。应用之间的差异具体表现在如下 几个方面:

  • 应用在编码、命名习惯、度量单位等方面会存在很大的差异。比 如不同应用对于用户的性别编码不同,有0和1、F和M等;不 同应用的用户ID含义相同,但字段名称不同,有user、user_id 等,不同应用对于金额的度量单位不同,有元、分等。
  • 应用出于性能和扩展性的考虑,或者随技术架构的演变,以及业 务的发展,采用不同的物理实现。拆分至不同类型数据库中,部 分数据采用关系型数据库存储(如Oracle, MySQL等),部分数 据采用NoSQL数据库存储(如HBase、Tair等)。拆分成同一类 型数据库中的多个物理表,比如对于淘宝商品,有商品主表和商 品扩展表,商品主表存储商品基本信息,商品扩展表存储商品特 殊信息,如不同产品线的定制化信息等;对于淘宝会员,有会员 主表和会员扩展表,会员主表存储用户基本信息,会员扩展表存 储用户扩展信息,如用户的各种标签信息等。
      所以数据由面向应用的操作型环境进入数据仓库后,需要进行数据 集成。将面向应用的数据转换为面向主题的数据仓库数据,本身就是一 种集成。具体体现在如下几个方面:
  • 命名规范的统一。表名、字段名等统一。
  • 字段类型的统一。相同和相似字段的字段类型统一。
  • 公共代码及代码值的统一。公共代码及标志性字段的数据类型、 命名方式等统一。
  • 业务含义相同的表的统一。主要依据高内聚、低耦合的理念,在 物理实现中,将业务关系大、源系统影响差异小的表进行整合; 将业务关系小、源系统影响差异大的表进行分而置之。通常有如 下几种集成方式:
      采用主从表的设计方式,将两个表或多个表都有的字段放在主表中(主要基本信息),从属信息分别放在各自的从表中。 对于主表中的主键,要么采用复合主键、源主键和系统或表 区别标志;要么采用唯一主键、“源主键和系统或表区别标志” 生成新的主键。通常建议采用复合主键的方式。
      直接合并,共有信息和个性信息都放在同一个表中。如果表 字段的重合度较低,则会出现大量空值,对于存储和易用性 会有影响,需谨慎选择。
      不合并,因为源表的表结构及主键等差异很大,无法合并, 使用数据仓库里的多个表存放各自的数据。
      维表的整合涉及的内容和上面介绍的几个方面相同,下面重点看表 级别的整合,有两种表现形式。
      第一种是垂直整合,即不同的来源表包含相同的数据集,只是存储 的信息不同。比如淘宝会员在源系统中有多个表,如会员基础信息表、 会员扩展信息表、淘宝会员等级信息表、天猫会员等级信息表,这些表 都属于会员相关信息表,依据维度设计方法,尽量整合至会员维度模型 中,丰富其维度属性。
      第二种是水平整合,即不同的来源表包含不同的数据集,不同子集 之间无交叉,也可以存在部分交叉。比如针对蚂蚁金服的数据仓库,其 采集的会员数据有淘宝会员、1688会员、国际站会员、支付宝会员等, 是否需要将所有的会员整合到一个会员表中呢?如果进行整合,首先需 要考虑各个会员体系是否有交叉,如果存在交叉,则需要去重;如果不 存在交叉,则需要考虑不同子集的自然键是否存在冲突,如果不冲突, 则可以考虑将各子集的自然键作为整合后的表的自然键;另一种方式是 设置超自然键,将来源表各子集的自然键加工成一个字段作为超自然 键。在阿里巴巴,通常采用将来源表各子集的自然键作为联合主键的方 式,并且在物理实现时将来源字段作为分区字段。
      有整合就有拆分,到底是整合还是拆分,由多种因素决定。下面两 节讨论维度的水平拆分和垂直拆分。

10.2.2 水平拆分

  维度通常可以按照类别或类型进行细分。比如淘系商品表,根据业 务线或行业等可以对商品进行细分,如淘宝的商品、天猫的商品、1688 的商品、飞猪旅行的商品、淘宝海外的商品、天猫国际的商品等。不同 分类的商品,其维度属性可能相同,也可能不同。比如航旅的商品和普 通的淘系商品,都属于商品,都有商品价格、标题、类型、上架时间、 类目等维度属性,但是航旅的商品除了有这些公共属性外,还有酒店、 景点、门票、旅行等自己独特的维度属性。
如何设计维度?针对此问题,主要有两种解决方案:方案1是将维 度的不同分类实例化为不同的维度,同时在主维度中保存公共属性,方 案2是维护单一维度,包含所有可能的属性。
  选择哪种方案?在数据模型设计过程中需要考虑的因素有很多,基 本不可能满足各个特性指标的最优化。在设计过程中需要重点考虑以下 三个原则。

  • 扩展性:当源系统、业务逻辑变化时,能通过较少的成本快速扩 展模型,保持核心模型的相对稳定性。软件工程中的高内聚、低 耦合的思想是重要的指导方针之一。
  • 效能:在性能和成本方面取得平衡。通过牺牲一定的存储成本, 达到性能和逻辑的优化。
  • 易用性:模型可理解性高、访问复杂度低。用户能够方便地从模 型中找到对应的数据表,并能够方便地查询和分析。

  根据数据模型设计思想,在对维度进行水平拆分时,主要考虑如下 两个依据。
  第一个依据是维度的不同分类的属性差异情况。当维度属性随类型 变化较大时,将所有可能的属性建立在一个表中是不切合实际的,也没 有必要这样做,此时建议采用方案1。定义一个主维度用于存放公共属 性;同时定义多个子维度,其中除了包含公共属性外,还包含各自的特 殊属性。比如在阿里巴巴数据仓库维度体系中,依据此方法,构建了商 品维度、航旅商品维度等。公共属性一般比较稳定,通过核心的商品维 度,保证了核心维度的稳定性;通过扩展子维度的方式,保证了模型的 扩展性。
  第二个依据是业务的关联程度。两个相关性较低的业务,耦合在一 起弊大于利,对模型的稳定性和易用性影响较大。比如在阿里巴巴数据 仓库维度体系中,对淘系商品和1688商品构建两个维度。虽然淘系和 1688在底层技术实现上是统一的,但属于不同的BU,业务各自发展; 在数据仓库层面,淘系和1688属于不同的数据集市,一般不会相互调 用,业务分析人员一般只针对本数据集市进行统计分析。如果设计成一 个维度,由于不同BU业务各自发展,1688业务变更,此维度需要变更, 淘宝业务变更亦然,稳定性很差;在易用性方面,会给数据使用方造成困扰。

10.2.3 垂直拆分

  在维度设计内容中,我们提到维度是维度建模的基础和灵魂,维度 属性的丰富程度直接决定了数据仓库的能力。在进行维度设计时,依据 维度设计的原则,尽可能丰富维度属性,同时进行反规范化处理。对于 具体实现时可能存在的问题:
  一是在“水平拆分”中提到的,由于维度分 类的不同而存在特殊的维度属性,可以通过水平拆分的方式解决此问题。
  二是某些维度属性的来源表产出时间较早,而某些维度属性的来源 表产出时间较晚;或者某些维度属性的热度高、使用频繁,而某些维度 属性的热度低、较少使用;或者某些维度属性经常变化,而某些维度属 性比较稳定。在“水平拆分”中提到的模型设计的三个原则同样适合解 决此问题。
  出于扩展性、产出时间、易用性等方面的考虑,设计主从维度。主 维表存放稳定、产出时间早、热度高的属性;从维表存放变化较快、产 出时间晚、热度低的属性。比如在阿里巴巴数据仓库中,设计了商品主 维度和商品扩展维度。其中商品主维度在每日的1:30左右产出,而商 品扩展维度由于有冗余的产岀时间较晚的商品品牌和标签信息,在每日 的3:00左右产出。另外,由于商品扩展维度有冗余的库存等变化较快 的数据,对于主维度进行缓慢变化的处理较为重要。通过存储的冗余和 计算成本的增加,实现了商品主模型的稳定和产出时间的提前,对于整 个数据仓库的稳定和下游应用的产出都有较大意义。

10.2.4 历史归档

  阿里巴巴历史截至当前的淘系(含淘宝、天猫和聚划算)商品有几 百亿条记录,在MaxCompute中,一天的全量数据占用约36TB的存储。 面对如此庞大的数据量,如何设计模型、如何降低存储、如何让下游方 便获取数据,成为必须要解决的问题。对于历史数据,是否存在前台已 经不再使用的情况?答案是肯定的,对于如此庞大的数据量,现有的技 术架构也很难处理。前台有一套数据归档策略,比如将商品状态为下架 或删除的且最近31天未更新的商品归档至历史库;具体逻辑根据不同 BU有不同的算法,且有特殊的规则。
  在数据仓库中,可以借用前台数据库的归档策略,定期将历史数据 归档至历史维表。在实践中,阿里巴巴数据仓库设计了商品维表和历史 商品维表,每天将历史数据归档至历史商品维表。关于归档策略,有以 下几种方式。
  归档策略1:同前台归档策略,在数据仓库中实现前台归档算法, 定期对历史数据进行归档。但存在一些问题,一是前台归档策略复杂, 实现成本较高;二是前台归档策略可能会经常变化,导致数据仓库归档 算法也要随之变化,维护和沟通成本较高。此方式适用于前台归档策略 逻辑较为简单,且变更不频繁的情况。
  归档策略2:同前台归档策略,但采用数据库变更日志的方式。对 于如此庞大的数据量,阿里巴巴采用的数据抽取策略一般是通过数据库 binlog日志解析获取每日增量,通过增量merge全量的方式获取最新的 全量数据。可以使用增量日志的删除标志,作为前台数据归档的标志。 通过此标志对数据仓库的数据进行归档。此方式不需要关注前台归档策 略,简单易行。但对前台应用的要求是数据库的物理删除只有在归档时 才执行,应用中的删除只是逻辑删除。
  归档策略3:数据仓库自定义归档策略。可以将归档算法用简单、直接的方式实现,但原则是尽量比前台应用晚归档、少归档。避免出现 数据仓库中已经归档的数据再次更新的情况。
  如果技术条件允许,能够解析数据库binlog日志,建议使用归档策 略2,规避前台归档算法。具体可以根据自身数据仓库的实际情况进行选择。

10.3 维度变化

10.3.1 缓慢变化维

  数据仓库的重要特点之一是反映历史变化,所以如何处理维度的变 化是维度设计的重要工作之一。缓慢变化维的提出是因为在现实世界 中,维度的属性并不是静态的,它会随着时间的流逝发生缓慢的变化。 与数据增长较为快速的事实表相比,维度变化相对缓慢。
  在一些情况下,保留历史数据没有什么分析价值;而在另一些情况 下,保留历史数据将会起到至关重要的作用。在Kimball的理论中,有 三种处理缓慢变化维的方式,下面通过简单的实例进行说明,具体细节 请翻阅Kimball的相关书籍。
  第一种处理方式:重写维度值。采用此种方式,不保留历史数据, 始终取最新数据。比如,商品所属的类目于2015年11月16日由类目 1变成类目2,采用第一种处理方式,变化前后的数据记录分别如表10.4 和表10.5所示。


  第二种处理方式:插入新的维度行。釆用此种方式,保留历史数据, 维度值变化前的事实和过去的维度值关联,维度值变化后的事实和当前 的维度值关联。同上面的例子,釆用第二种处理方式,变化前的数据记 录同表10.4,变化后的数据记录如表10.6所示。

  第三种处理方式:添加维度列。采用第二种处理方式不能将变化前 后记录的事实归一为变化前的维度或者归一为变化后的维度。比如根据 业务需求,需要将11月份的交易金额全部统计到类目2±,釆用第二 种处理方式无法实现。针对此问题,釆用第三种处理方式,保留历史数 据,可以使用任何一个属性列。同上面的例子,采用第三种处理方式, 变化前后的数据记录分别如表10.7和表10.8所示。通过变化后的商品 表和订单表关联,可以根据不同的业务需求,将11月份的交易金额全 部统计到类目2或类目1上。


  对于选择哪种方式处理缓慢变化维,并没有一个完全正确的答案, 可以根据业务需求来进行选择。比如根据商品所属的类目统计淘宝2015 年11月的成交额,商品所属的类目于2015年11月16日由类目1变成 类目2,假设业务需求方不关心历史数据,将所有的成交额都统计到最 新的类目2上,则不需要保存历史数据;假设类目1属于某个业务部门, 类目2属于另一个业务部门,不同业务部门需要统计各自的业绩,则需 要保留历史数据。

10.3.2 快照维表

  在“维度的基本概念”中,介绍了自然键和代理键的定义,在Kimball 的维度建模中,必须使用代理键作为每个维表的主键,用于处理缓慢变化维。
  但在阿里巴巴数据仓库建设的实践过程中,虽然使用的是Kimball 的维度建模理论,但实际并未使用代理键。那么为什么不使用代理键? 如何处理缓慢变化维?
  首先看“为什么不使用代理键”这个问题。第一个原因是,阿里巴 巴数据量庞大,使用的是阿里巴巴自助知识产权的分布式计算平台 MaxComputeo对于分布式计算系统,不存在事务的概念,对于每个表 的记录生成稳定的全局唯一的代理键难度很大,此处稳定指某条记录每 次生成的代理键都相同。第二个原因是,使用代理键会大大增加ETL 的复杂性,对ETL任务的开发和维护成本很高。
  接下来讨论不使用代理键如何处理缓慢变化维的问题。在阿里巴巴 数据仓库实践中,处理缓慢变化维的方法是采用快照方式。数据仓库的 计算周期一般是每天一次,基于此周期,处理维度变化的方式就是每天 保留一份全量快照数据。比如商品维度,每天保留一份全量商品快照数 据。任意一天的事实均可以获取到当天的商品信息,也可以获取到最新 的商品信息,通过限定日期,采用自然键进行关联即可。此方法既有优 点,也有弊端。
  优点主要有以下两点:

  • 简单而有效,开发和维护成本低。
  • 使用方便,理解性好。数据使用方只需要限定日期,即可获取到 当天的快照数据。任意一天的事实快照和维度快照通过维度的自 然键进行关联即可。
      弊端主要体现在存储的极大浪费上。比如某维度,每天的变化量占 总体数据量的比例很低,在极端情况下,每天无变化,使得存储浪费很 严重。此方法主要就是实现了牺牲存储获取ETL效率的优化和逻辑上 的简化。但是一定要杜绝过度使用这种方法,而且必须要有对应的数据 生命周期制度,清除无用的历史数据。
      综合来看,由于现在存储成本远低于CPU、内存等的成本,此方 法弊大于利。那么是否有方法既可以实现上面的优点,同时又可以很好 地降低存储呢?答案是肯定的,那就是阿里巴巴的极限存储。

10.3.3 极限存储

  首先来看历史拉链存储。历史拉链存储是指利用维度模型中缓慢变 化维的第二种处理方式。这种处理方式是通过新增两个时间戳字段 (start_dt和end_dt),将所有以天为粒度的变更数据都记录下来。通常 分区字段也是时间戳字段。
  例如,2016年1月1日,卖家A在淘宝网发布了 B、C两个商品, 前端商品表将生成两条记录tl、t2; 1月2日,卖家A将B商品下架了, 同时又发布了商品D,前端商品表将更新记录tl,又新生成记录t3;采 用全量存储方式,在1月1日这个分区中存储tl和t2两条记录,在1 月2日这个分区中存储更新后的tl以及t2、t3记录。数据存储记录如 表10.9所示。

  如果采用历史拉链存储,数据存储记录如表10.10所示。对于不变 的数据,不再重复存储。

  这样下游应用可以通过限制时间戳字段来获取历史数据。例如,用户 访问1月1日的数据,只需要限制stat_dt<=20160101和end_dt>20160101 即可。
  但是这种存储方式对于下游使用方存在一定的理解障碍,特别是 ODS数据面向的下游用户包括数据分析师、前端开发人员等,他们不 怎么理解维度模型的概念,因此会存在较高的解释成本。另外,这种存 储方式用start_dt和end_dt做分区,随着时间的推移,分区数量会极度 膨胀,而现行的数据库系统都有分区数量限制。
  为了解决上述两个问题,阿里巴巴提出采用极限存储的方式来处理。
1.透明化
  底层的数据还是历史拉链存储,但是上层做一个视图操作或者在 Hive里做一个hook,通过分析语句的语法树,把对极限存储前的表的 查询转换成对极限存储表的查询。对于下游用户来说,极限存储表和全量存储方式是一样的:
2.分月做历史拉链表
  假设用start_dt和end_dt做分区,并且不做限制,那么可以计算出 一年历史拉链表最多可能产生的分区数是:365x364/2=66430个。如果 在每个月月初重新开始做历史拉链表,目录结构如下:

  再计算一年最多可能产生的分区数是:12x(1+(30+29)/2)=5232个。
  采用极限存储的处理方式,极大地压缩了全量存储的成本,又可以 达到对下游用户透明的效果,是一种比较理想的存储方式。但是其本身 也有一定的局限性,首先,其产出效率很低,大部分极限存储通常需要 ?-2,其次,对于变化频率高的数据并不能达到节约成本的效果。因此, 在实际生产中,做极限存储需要进行一些额外的处理。

  • 在做极限存储前有一个全量存储表,全量存储表仅保留最近一段 时间的全量分区数据,历史数据通过映射的方式关联到极限存储 表。即用户只访问全量存储表,所以对用户来说极限存储是不可 见的。
  • 对于部分变化频率频繁的字段需要过滤。例如,用户表中存在用 户积分字段,这种字段的值每天都在发生变化,如果不过滤的话, 极限存储就相当于每个分区存储一份全量数据,起不到节约存储 成本的效果。

10.3.4 微型维度

  采用极限存储,需要避免维度的过度增长。比如对于商品维表,每 天20多亿条数据,如果在设计商品维度时,将值变化频繁的属性加入 到商品维度中,极限情况是每天所有商品数据都发生变化,此时,极限 存储没有意义;反之,每天所有商品数据都不发生变化,此时,只需要 存储一天的数据即可。
  通过将一些属性从维表中移出,放置到全新的维表中,可以解决维 度的过度增长导致极限存储效果大打折扣的问题。其中一种解决方法就 是上一节提到的垂直拆分,保持主维度的稳定性;另一种解决方式是釆 用微型维度。
  微型维度的创建是通过将一部分不稳定的属性从主维度中移出,并 将它们放置到拥有自己代理键的新表中来实现的。这些属性相互之间没 有直接关联,不存在自然键。通过为每个组合创建新行的一次性过程来 加载数据。比如淘宝用户维度,用户的注册日期、年龄、性别、身份信 息等基本不会发生变化,但用户VIP等级、用户信用评价等级会随着用 户的行为不断发生变化。其中VIP等级共有8个值,即-1〜6;用户信 用评价等级共有18个值。假设基于VIP等级和用户信用评价等级构建 微型维度,则在此微型维度中共有8x18个组合,即144条记录,代理 键可能是1~144。
  这里以淘宝交易事实表为例,其他维度忽略,星形模式可能表示如 图10.3所示。

  但在阿里巴巴数据仓库实践中,并未使用此技术,主要有以下几点 原因:

  • 微型维度的局限性。微型维度是事先用所有可能值的组合加载 的,需要考虑每个属性的基数,且必须是枚举值。很多属性可能 是非枚举型,比如数值类型,如VIP分数、信用分数等;时间类 型,如上架时间、下架时间、变更时间等。
  • ETL逻辑复杂。对于分布式系统,生成代理键和使用代理键进行 ETL加工都非常复杂,ETL开发和维护成本过高。
  • 破坏了维度的可浏览性。买家维度和微型维度通过事实表建立联 系,无法基于VIP等级、信用等级进行浏览和统计。可以通过在 买家维度中添加引用微型维度的外键部分来解决此问题,但带来 的问题是微型维度未维护历史信息。

10.4特殊维度

10.4.1 递归层次

  上面我们学习了维度的层次结构,即维度属性以层次方式或一对多 的方式相互关联;或者描述为不同维度之间的主从关系,比如商品和类 目的关系、商品和品牌的关系等。本节的递归层次指的是某维度的实例 值的层次关系,比如淘宝类目体系,示例如表10.11所示。

  维度的递归层次,按照层级是否固定分为均衡层次结构和非均衡层 次结构。比如类目,有固定数量的级别,分别是叶子类目、五级类目、 四级类目、三级类目、二级类目、一级类目;地区,分别是乡镇/街道、 区县、城市、省份、国家。对于这种具有固定数量级别的递归层次,称 为“均衡层次结构二比如公司之间的关系,每个公司可能存在一个母 公司,但可能没有固定的一级、二级等层级关系。对于这种数量级别不 固定的递归层次,称为“非均衡层次结构”。
  淘宝交易事实表通过叶子类目和类目维表关联,如何统计类目ID 为21的最近一天的GMV?第一步,获取父类目ID等于20的所有类目, 称为子类目。第二步,对于每个子类目,如果为叶子类目,则终止;如 果非叶子类目,则此类目ID作为父类目ID执行第一步,直到找到所有 叶子类目,如圣诞服饰(50026579)、台历(121456022)等。将所有叶 子类目和交易事实表关联进行统计汇总,即可得到类目ID等于21的最 近一天的GMV,也就是家具日用类目的最近一天的GMV。在物理实现 时,可以使用递归SQL实现,如Oracle中的connect by语句。

  通过数据探查得知ID等于21的类目属于一级类目(父类目ID等 于0),统计其最近一天的GMV的过程,称为上钻;在递归层次中进行 上钻和下钻是很常见的。由于很多数据仓库系统和商业智能工具不支持 递归SQL,且用户使用递归SQL的成本较高,所以在维度模型中,需 要对此层次结构进行处理。
1.层次结构扁平化
  降低递归层次使用复杂度的最简单和有效的方 法是层次结构的扁平化,通过建立维度的固定数量 级别的属性来实现,可以在一定程度上解决上钻和 下钻的问题。对于均衡层次结构,采用扁平化最有 效。
  对于淘宝商品类目,通过层次结构扁平化之后, 类目维表示如图10.4所示。每个类目保存一条记录, 并将其所属的各类目层级属性化。其中,对于高层 级类目,由于其无低层级类目,则低层级类目置为 空值。

  具体数据存储示例如表10.12所示,其中四级和五级类目省略。

  如何统计类目ID为21的最近一天的GMV?将淘宝交易事实表通 过叶子类目和类目维表的类目ID关联之后,限制一级类目ID等于21 之后进行汇总统计,即可以得到类目ID等于21的最近一天的GMVO 其使用方便性得到大大提高,但存在如下三个方面的问题:

  • 针对某类目上钻或下钻之前,必须知道其所属的类目层级,然后才 能决定限制哪一级类目。如上述示例,限制一级类目ID等于21。
  • 假设分三级类目统计最近一天的GMV,由于某些叶子类目直接 是一级类目或二级类目(比如类目ID等于121456022的类目, 其是叶子类目),和交易事实表关联之后,其对应的三级类目为 空,导致根据三级类目统计最近一天的GMV时,类目ID等于 121456022的交易无法被统计到。下游数据统计时,为了规避此 问题,如果此类目对应的三级类目为空,则取二级类目;如果二 级类目仍为空,则取一级类目。

  所以针对此问题,下游数据统计时,类目层次结构扁平化的另一种 方式是回填,将类目向下虚拟,具体数据存储示例如表10.13所示,其 中粗体部分为回填内容。阿里巴巴中文站的类目体系使用此种方式。
- 扁平化仅包含固定数量的级别,对于非平衡层次结构,可以通过
预留级别的方式来解决,但扩展性较差。
2.层次桥接表
  针对层次结构扁平化所存在的问题,可以采用桥接表的方式来解 决,不需要预先知道所属层级,不需要回填,也可解决非均衡层次结构 的问题。与扁平化方法相比,该方法适合解决更宽泛的分析问题,灵活 性好;但复杂性高,使用成本高。
  仍然以类目为例,模型设计如图10.5所示。
  对于上面提到的类目,使用树形结构表示如图10.6所示。

  针对此类目树,类目桥接表的内容如表10.14所示。

  假设针对类目21进行下钻操作,步骤如下:
  限制类目表的类目ID等于21,通过类目ID和类目桥接表的父类 目ID关联,使两表建立连接;通过类目桥接表的子类目ID和交易事实 表的类目ID关联,使两表建立连接;接下来即可针对订单事实进行下 钻操作。涉及类目桥接表的数据见表10.14中“父类目ID"字段的粗体 部分(21)。
  假设针对类目50026579进行上钻操作,步骤如下:
  限制类目表的类目ID等于50026579,通过类目ID和类目桥接表 的子类目ID关联,使两表建立连接,通过类目桥接表的父类目ID关联, 使两表建立连接;接下来即可针对订单事实进行上钻操作。涉及类目桥 接表的数据见表10.14中“子类目ID”字段的粗体部分(50026579).
  可以看到,层次桥接表解决了层次结构扁平化带来的一些问题;但 是其加工逻辑复杂,使用逻辑复杂,而且由于事实表和桥接表的多对多 关系而带来了双重计算的隐患。在实际应用中可以根据具体的业务需求 来选择技术方案,比如在统计分析或报表中,一般都是按照固定级别进 行,如按照一级类目统计GMV、按照省份统计GMV等,现在的扁平 化设计完全可以满足需求,而不需要引入复杂的桥接表。很多时候,简单、直接的技术方案却是最好的解决方案。

10.4.2 行为维度

  在阿里巴巴的数据仓库中,存在很多维表,如卖家主营类目维度、 卖家主营品牌维度、用户常用地址维度等。其中卖家主营类目和主营品 牌通过卖家的商品分布和交易分布情况,采用算法计算得到;卖家常用 地址通过最近一段时间内物流中卖家的发货地址和买家的收货地址进 行统计得到。类似的维度,都和事实相关,如交易、物流等,称之为“行 为维度”,或“事实衍生的维度”。
  按照加工方式,行为维度可以划分为以下几种:

  • 另一个维度的过去行为,如买家最近一次访问淘宝的时间、买家 最近一次发生淘宝交易的时间等。
  • 快照事实行为维度,如买家从年初截至当前的淘宝交易金额、买 家信用分值、卖家信用分值等。
  • 分组事实行为维度,将数值型事实转换为枚举值。如买家从年初 截至当前的淘宝交易金额按照金额划分的等级、买家信用分值按 照分数划分得到的信用等级等。
  • 复杂逻辑事实行为维度,通过复杂算法加工或多个事实综合加工 得到。如前面提到的卖家主营类目,商品热度根据访问、收藏、 加入购物车、交易等情况综合计算得到。
      对于行为维度,有两种处理方式,其中一种是将其冗余至现有的维 表中,如将卖家信用等级冗余至卖家维表中,另一种是加工成单独的行 为维表,如卖家主营类目。具体釆用哪种方式主要参考如下两个原则:
      第一,避免维度过快增长。比如对商品表进行了极限存储,如果将 商品热度加入现有的商品维表中,则可能会使每日商品变更占比过高, 从而导致极限存储效果较差。
      第二,避免耦合度过高。比如卖家主营类目,加工逻辑异常复杂, 如果融合进现有的卖家维表中,那么过多的业务耦合会导致卖家维表刷 新逻辑复杂、维护性差、产出延迟等。

10.4.3 多值维度

  对于多值维度,一种情况是事实表的一条记录在某维表中有多条记 录与之对应。比如对于淘宝交易订单,买家一次购买了多种商品,如一 件毛衣和两双袜子,称为交易父订单;对于每种商品的交易,称为交易 子订单;此交易父订单有两个子订单与之对应。假设设计交易父订单事 实表,则对于此事实表的每一条记录,在商品表中都有一到多条记录与 之对应。
  针对多值维度,常见的处理方式有三种,可以根据业务的表现形式 和统计分析需求进行选择。
  第一种处理方式是降低事实表的粒度。在淘宝交易中,前台业务和 商业智能关注交易子订单,所以在数据仓库模型设计中,将交易订单设计为子订单粒度,对于每个子订单,只有一种商品与之对应。对于其中 的事实,则采用分摊到子订单的方式来解决。但很多时候,事实表的粒 度是不能降低的,多值维度的出现是无法避免的。
  第二种处理方式是采用多字段。比如在房地产销售中,每次合同签 订都可能存在多个买受方的情况,如夫妻合买等。对于合同签订事实表, 每条记录可能对应多个买受方,而合同已经是此事实中的最细粒度,无 法通过降低粒度的方式来解决。由于合同签订的买受人一般不会太多, 所以一般采用多字段方式。考虑到扩展性,可以通过预留字段的方式, 如超过三个买受方时,其余买受方填写至“其他买受方”字段。模型设 计如图10.7所示。

  第三种处理方式是釆用较为通用的桥接表。桥接表方式更加灵活、 扩展性更好,但逻辑复杂、开发和维护成本较高,可能带来双重计算的 风险,选择此方式需慎重。通过在事实表和维表之间开发一个分组表, 通过此分组表建立连接。模型设计如图10.8所示,其中桥接表包含和 事实表关联的分组KEY,以及作为买受方维表外键的买受方ID。如果 事实表的一条记录对应两个买受方,则桥接表针对这两个买受方建立两 条记录,分组KEY相同。
  假设根据买受方籍贯统计2015年的合同总金额,如果某合同有两 个买受方,籍贯分别是浙江和山东,那么此合同总金额将会分别统计浙 江和山东的,造成双重计算。双重计算不一定是错误,对于一些业务需 求是合理的;但对于另一些业务需求,则需要规避。

10.4.4 多值属性

  维表中的某个属性字段同时有多个值,称之为“多值属性”。它是多 值维度的另一种表现形式。在阿里巴巴的数据仓库中,存在很多维表, 如商品SKU维表、商品属性维表、商品标签维表等。每个商品均有一到 多个SKU、一到多个属性和一到多个标签,所以商品和SKU、属性、标 签都是多对多的关系。淘宝商品SKU和属性信息示例如图10.9所示。

  对于多值属性,常见的处理方式有三种,可以根据具体情况进行选择。 第一种处理方式是保持维度主键不变,将多值属性放在维度的一个 属性字段中。比如对于商品属性(注:此属性是业务上的含义,和维度建模中的维度属性含义不同),可以通过k-v对的形式放在property字 段中,数据示例如下:10281239:156426871; 137396765:29229; 137400766: 3226633O此种处理方式扩展性好,但数据使用较为麻烦。
  第二种处理方式也是保持维度主键不变,但将多值属性放在维度的 多个属性字段中。比如卖家主营类目,由于卖家店铺中可能同时会销售 男装、女装、内衣等,所以卖家主营类目可能有多个,但业务需求是只 取根据算法计算得到的TOP3。针对此种情况,维度的多值属性字段具 体值的数量固定,可以采用多个属性字段进行存储,方便数据统计分析 和报表展示。如果多值属性字段具体值的数量不固定,则可以釆用预留 字段的方式,但扩展性较差。卖家主营类目维度设计如图10.10所示。

  第三种处理方式是维度主键发生变化,一个维度值存放多条记录。 比如商品SKU维表,对于每个商品,有多少SKU,就有多少记录,主 键是商品的ID和SKU的IDO此种处理方式扩展性好,使用方便,但 需要考虑数据的急剧膨胀情况。比如淘宝商品属性表釆用了此种处理方 式,数据记录达到几百亿的级别。

10.4.5 杂项维度

  在维度建模中,有一种维度叫Junk Dimension,中文一般翻译为“杂项维度”。杂项维度是由操作型系统中的指示符或者标志字段组合而成 的,一般不在一致性维度之列。比如淘宝交易订单的交易类型字段,包 括话费充值、司法拍卖、航旅等类型;支付状态、物流状态等,它们在 源系统中直接保存在交易表中。
  一个事实表中可能会存在多个类似的字段,如果作为事实存放在事 实表中,则会导致事实表占用空间过大;如果单独建立维表,外键关联 到事实表,则会出现维度过多的情况;如果将这些字段删除,则会有人 不同意。
  这时,通常的解决方案就是建立杂项维度,将这些字段建立到一个 维表中,在事实表中只需保存一个外键即可。多个字段的不同取值组成 一条记录,生成代理键,存入维表中,并将该代理键保存到相应的事实 表字段下。建议不要直接使用所有的组合生成完整的杂项维表,在抽取 遇到新的组合时生成相应的记录即可。杂项维度的ETL过程比一般的 维度略微复杂些。
  但在阿里巴巴的实践中,杂项维度不仅包含上述指示符、状态或分 类等枚举字段,还包含很多非枚举字 段,如交易留言、交易属性(由若干 k-v对组成)、交易标签(由二进制位 表示)等。针对这些字段,不可能生 成所有的组合;同时,由于在分布式 计算系统中生成代理键的复杂度,一 般在逻辑建模中,会使用实体的主键 作为杂项维度的主键。只考虑杂项维 度,忽略其他维度,如图10.11所示。

  但子订单维度一般是逻辑模型,物理实现时不进行物理化,订单杂 项维度和其他维度一起,会将维度属性退化至事实表中,详情在事实表 中描述。

注:本章节部分理论来自于Christopher Adamson的Star Schema -The Complete Reference 和 Ralph Kimball 的 The Data Warehouse Toolkit-The Definitive Guide to Dimensional Modelingo本书结合阿里的实践进行讲解,细节 内容请参考各自著作进行学习。

《大数据之路:阿里巴巴大数据实践》-第2篇 数据模型篇 -第10章 维度设计相关推荐

  1. 读《大数据之路-阿里巴巴大数据实践》数据模型篇笔记

    读<大数据之路-阿里巴巴大数据实践>数据模型篇 七 建模综述 OLTP 面向数据 随机读写 3NF OLAP 批量读写 不关注一致性更关心数据整合 ER模型–衍生出dataVault 维度 ...

  2. 《大数据之路 阿里巴巴大数据实践》笔记

    此书下载传送门http://www.java1234.com/a/javabook/yun/2018/0308/10578.html 第1章 总述 阿里巴巴大数据系统体系主要分为,数据采集.数据计算. ...

  3. 大数据之路 阿里巴巴大数据实践 读书笔记

    一 .总述 人类正在从IT时代走向DT时代.现在的数据呈爆炸式增长,其潜在的巨大价值有待发掘.但是如果不对数据进行有序.有结构的分类组织和存储,它将变成一场灾难. 在阿里内部,数据的存储达到EB级别. ...

  4. 《大数据之路-阿里巴巴大数据实践》读书笔记

    ps:这本书主讲阿里的大数据体系架构方案,从底层到高层阐述,目前对我来说此书的难度较大,不是很懂,大部分为对原书的引用归纳,我会给出相应的大牛的关于此书的读书笔记的传送门供参考.以下为大牛关于本书的读 ...

  5. 大数据之路——阿里巴巴大数据实践:总述

    阿里巴巴大数据系统架构图: Aplus.JS是web端日志采集技术 UserTask是APP端日志采集技术 TimeTunel(TT)是一个实时消息处理平台,类似于kafka+storm DataX是 ...

  6. 《大数据之路-阿里巴巴大数据实践》第一章 总述

  7. 数据仓库进阶 《阿里大数据之路》第二篇 数据模型篇 (完整版)

    第8章 大数据领域建模综述 此文章为学习笔记,有兴趣的小伙伴可以根据以下指引获取更多,学习内容链接如下: 视频:[一起啃书]阿里大数据之路数据仓库建模基础理论研读(已完结)_哔哩哔哩_bilibili ...

  8. 《大数据之路:阿里巴巴大数据实践》-第2篇 数据模型篇 -第8章 大数据领域建模综述

    <大数据之路:阿里巴巴大数据实践>系列丛书  第1章 总述 第1篇 数据技术篇  第2章 日志釆集  第3章 数据同步  第4章 离线数据开发  第5章 实时技术  第6章 数据服务  第 ...

  9. 《大数据之路:阿里巴巴大数据实践》第二篇 数据模型篇-读书笔记

    目录 8.大数据领域建模综述 8.1 为什么需要数据建模 8.2 关系数据库系统和数据仓库 8.3 从OLTP和OLAP系统的区别看模型方法论的选择 8.4 典型的数据仓库建模方法论 8.4.1 ER ...

  10. 数据仓库理论进阶 - 01 《阿里大数据之路》第二篇数据模型篇

    第8章 大数据领域建模综述 此文章为学习笔记,有兴趣的小伙伴可以根据以下指引获取更多,学习内容链接如下: 视频:[一起啃书]阿里大数据之路数据仓库建模基础理论研读(已完结)_哔哩哔哩_bilibili ...

最新文章

  1. 重塑技术引擎 阿里落地全球最大规模云原生实践支撑双11
  2. ubuntu fstab 示例
  3. stata中计算公式命令_#stata中哪个命令和stats命令等价#stata中计算命令
  4. [画图]几何图形绘制测试
  5. 【学校作业】学生数据打印
  6. idea的setting界面怎么进_Mac版YY语音进入频道失败怎么破?
  7. 正则表达式之全部符号解释
  8. 基于链表的模拟21点游戏 C语言
  9. 菜鸟系列之C/C++经典试题(七)
  10. python防反编译_linux python如何反编译成源码
  11. linux服务器之LVS、Nginx和HAProxy负载均衡器对比
  12. 你所不了解的“三消”游戏
  13. windows优化大师怎么用_用智慧和爱心经营——班主任经验交流录音稿
  14. 2021农行研发中心面试题总结
  15. 微信公众号开发引导用户关注公众号
  16. eclipse debug 多线程
  17. deebot扫地机器人说明书_ecovacs扫地机器人730使用说明书_deebot扫地机器说明书
  18. 全球最小的一款P2P软件——eMuleBT软件框架分析
  19. 任务列表,任务办理,转办任务,委派任务
  20. zabbix 监控81端口

热门文章

  1. XZ_Swift 之HealthKit 获取手机计步统计
  2. windows系统磁盘空间清理工具SDelete
  3. 矩阵迹的几何意义是什么?
  4. 开发本地O2O分销系统有什么优势 O2O电子商务模式有哪些特点?
  5. iphone11 android,iphone11launcher
  6. 在线二进制取余计算机,十进制转二进制和十六进制计算器
  7. jquery+cropper剪切、旋转、缩放图片
  8. 安捷伦色质谱仪维修四极杆驱动器维修G2571
  9. 14、CSS渲染:CSS是如何绘制颜色的?
  10. windows批处理 复制文件和文件夹子文件夹