大数据之路读书笔记-10维度设计

文章目录

  • 大数据之路读书笔记-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.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 类目名称等。 ID一般用于不同表之间的关联,而名称一般用于报表标签。

(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 一致性维度和交叉探查

构建企业级数据仓库不可能一蹴而就,一般采用迭代式的构建过程。 而单独构建存在的问题是形成独立型数据集市,导致严重的不一致性。 Kimball 的数据仓库总线架构提供了一种分解企业级数据仓库规划任务的合理方法,通过构建企业范围内一致性维度和事实来构建总线架构。

数据仓库总线架构的重要基石之一就是一致性维度。在针对不同数据域进行迭代构建或并行构建时,存在很多需求是对于不同数据域的业务过程或者同一数据域的不同业务过程合并在一起观察。比如对于日志数据域,统计了商品维度的最近一天的 PV 对于交易数据域,统计了商品维度的最近一天的下单 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是将维度的不同分类实例化为不同的维度,同时在主维度中保存公共属性;方案二是维护单一维度,包含所有可能的属性。

选择哪种方案?在数据模型设计过程中需要考虑的因素有很多,基本不可能满足各个特性指标的最优化。在设计过程中需要重点考虑以下三个原则。

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

第一个依据是维度的不同分类的属性差异情况。当维度属性随类型变化较大时,将所有可能的属性建立在一个表中是不切合实际的,也没有必要这样做,此时建议采用方案1。定义一个主维度用于存放公共属性;同时定义多个子维度,其中除了包含公共属性外,还包含各自的特殊属性。比如在阿里巴巴数据仓库维度体系中,依据此方法,构建了商品维度、航旅商品维度等。公共属性一般比较稳定,通过核心的商品维度,保证了核心维度的稳定性;通过扩展子维度的方式,保证了模型的扩展性。

第二个依据是业务的关联程度。两个相关性较低的业务,稠合在一起弊大于利,对模型的稳定性和易用性影响较大。比如在阿里巴巴数据仓库维度体系中,对淘系商品和 1688 商品构建两个维度。虽然淘系和1688 在底层技术实现上是统一的,但属于不同的 BU ,业务各自发展在数据仓库层面,淘系和1688 属于不同的数据集市,一般不会相互调用,业务分析人员一般只针对本数据集市进行统计分析。如果设计成一个维度,由于不同业务各自发展, 1688 业务变更,此维度需要变更,淘宝业务变更亦然,稳定性很差;在易用性方面,会给数据使用方造成困扰。

10.2.3 垂直拆分

在维度设计内容中,我们提到维度是维度建模的基础和灵魂,维度属性的丰富程度直接决定了数据仓库的能力。在进行维度设计时,依据维度设计的原则,尽可能丰富维度属性,同时进行反规范化处理。对于具体实现时可能存在的问题,一是在“水平拆分”中提到的,由于维度分类的不同而存在特殊的维度属性,可以通过水平拆分的方式解决此问题。

二是某些维度属性的来源表产出时间较早,而某些维度属性的来表产出时间较晚;或者某些维度属性的热度高、使用频繁,而某些维度属性的热度低、较少使用 或者某些维度属性经常变化,而某些维度属性比较稳定。在“水平拆分”中提到的模型设计的三个原则同样适合解决此问题。

出于扩展性、产出时间、易用性等方面的考虑,设计主从维度。主维表存放稳定、产出时间早、热度高的属性;从维表存放变化较快、产出时间晚、热度低的属性。比如在阿里巴巴数据仓库中,设计了商品维度和商品扩展维度。其中商品主维度在每日的 1:30 左右产出,而商品扩展维度由于有冗余的产出时间较晚的商品品牌和标签信息 ,在每天3:00 左右产出。另外,由于商品扩展维度有冗余的库存等变化较快的数据,对于主维度进行缓慢变化的处理较为重要。通过存储的冗余和计算成本的增加,实现了商品主模型的稳定和产出时间的提前,对于整个数据仓库的稳定和下游应用的产出都有较大意义。

10.2.4 历史归档

阿里巴巴历史截至当前的淘系(含淘宝、天猫和聚划算)商品有几百亿条记录,在 Max Compute 中,一天的全量数据占用约 6TB 的存储。面对如此庞大的数据量,如何设计模型、如何降低存储、如何让下游方便获取数据,成为必须要解决的问题。对于历史数据,是否存在前台已经不再使用的情况?答案是肯定的,对于如此庞大的数据量,现有的技术架构也很难处理。前台有一套数据归档策略,比如将商品状态为下架或删除的且最近 31 天未更新的商品归档至历史库 具体逻辑根据不同BU 有不同的算法,且有特殊的规则。

在数据仓库中,可以借用前台数据库的归档策略定期将历史数据归档至历史维表。在实践中,网里巴巴数据仓库设计了商品维表和历史商品维表,每天将历史数据归档至历史商品维表。关于归档策略,有以下几种方式。
归档策略 :同前台归档策略,在数据仓库中实现前台归档算法,定期对历史数据进行归档。但存在一些问题,一是前台归档策略复杂,实现成本较高 二是前台归档策略可能会经常变化 导致数据仓库归档算法也要随之变化,维护和沟通成本较高。此方式适用于前台归档策略逻辑较为简单,且变更不频繁的情况。

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

10.3.2 快照维表

在“维度的基本概念”中,介绍了自然键和代理键的定义,在 Kimball的维度建模中,必须使用代理键作为每个维表的主键,用于处理缓慢变化维。

但在阿里巴巴数据仓库建设的实践过程中,虽然使用的是 Kimball的维度建模理论,但实际并未使用代理键。那么为什么不使用代理键?如何处理缓慢变化维?

首先看“为什么不使用代理键”这个问题。第一个原因是,阿里巴巴数据量庞大,使用的是阿里巴巴自助知识产权的分布式计算平台Max Compute 。对于分布式计算系统,不存在事务的概念,对于每个的记录生成稳定的全局唯一的代理键难度很大,此处稳定指某条记录每次生成的代理键都相同。第二个原因是,使用代理键会大大增加 ETL的复杂性,对ETL 任务的开发和维护成本很高。

接下来讨论不使用代理键如何处理缓慢变化维的问题。在阿里巴巴数据仓库实践中,处理缓慢变化维的方法是采用快照方式。数据仓库的计算周期一般是每天一次,基于此周期,处理维度变化的方式就是每天保留一份全量快照数据。比如商品维度,每天保留一份全量商品快照数据。任意一天的事实均可以获取到当天的商品信息 ,也可以获取到最新的商品信息,通过限定日期,采用自然键进行关联即可。此方法既有优点,也有弊端。

优点主要有以下两点:
● 简单而有效,开发和维护成本低。
● 使用方便,理解性好。数据使用方只需要限定日期,即可获取到当天的快照数据。任意一天的事实快照和维度快照通过维度的自然键进行关联即可。
弊端主要体现在存储的极大浪费上。比如某维度,每天的变化量占总体数据量的比例很低,在极端情况下,每天无变化,使得存储浪费很严重。此方法主要就是实现了牺牲存储获取 TL 效率的优化和逻辑上的简化。但是一定要杜绝过度使用这种方法,而且必须要有对应的数据生命周期制度,清除无用的历史数据。

综合来看,由于现在存储成本远低于 CPU 、内存等的成本,此方法弊大于利。那么是否有方法既可以实现上面的优点,同时又可以很好地降低存储呢?答案是肯定的,那就是阿里巴巴的极限存储。

10. 3.3 极限存储

首先来看历史拉链存储。历史拉链存储是指利用维度模型中缓慢变化维的第二种处理方式。这种处理方式是通过新增两个时间戳字段(sta rt_dt end_dt ),将所有以天为粒度的变更数据都记录下来。通常分区字段也是时间戳字段。

例如, 2016年1月1日,卖家在淘宝网发布了两个商品,前端商品表将生成两条记录 tl 、t2.1月2 日,卖家A将B商品下架了,同时又发布了商品D,前端商品表将更新记录 t1 ,又新生成记录 t3;采用全量存储方式,在1月1日这个分区中存储 t1和t2 两条记录:在1月2日这个分区中存储更新后的 tl 以及 t2、t3 记录。数据存储记录如表10.9 所示。
如果采用历史拉链存储,数据存储记录如表 10.10 示。对于不变的数据,不再重复存储。
这样下游应用可以通过限制时间戳字段来获取历史数据。例如,用户 访问1月1日的数据,只需要限制 stat_dt<=20160101end_dt>20160101即可。

但是这种存储方式对于下游使用方存在一定的理解障碍,特别ODS 数据面向的下游用户包括数据分析师、前端开发人员等,他们不怎么理解维度模型的概念,因此会存在较高的解释成本。另外,这种储方式用 start_dt和end_dt 做分区,随着时间的推移,分区数量会极度膨胀,而现行的数据库系统都有分区数限制。

为了解决上述两个问题,阿里巴巴提出来用极限存储的方式来处理。
1 透明化
底层的数据还是历史拉链存储,但是上层做一个视图操作或者在Hive 里做一个hook ,通过分析语句的语法树,把对极限存储前的表的查询转换成对极限存储表的查询。对于下游用户来说,极限存储表和全存储方式是一样的:
2. 分月做历史拉链表
假设用 start_dt和 end dt 做分区,并且不做限制,那么可以计算出一年历史拉链表最多可能产生的分区数是 365x36/2=66430个。如果
在每个月月初重新开始做历史拉链表,目录结构如下
再计算一年最多可能产生的分区数是: 12 ×( 1 +(30+29)/2)=5232 个。
采用极限存储的处理方式,极大地压缩了全量存储的成本,又可以达到对下游用户透明的效果,是一种比较理想的存储方式。但是其本身也有一定的局限性,首先,其产出效率很低,大部分极限存储通常需要t-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.1 示。
维度的递归层次,按照层级是否固定分为均衡层次结构和非均衡层次结构。比如类目,有固定数量的级别,分别是叶子类目、五级类 目、四级类目、三级类目、二级类目、 级类曰:地区,分别是乡镇/街道区县、城市、省份、国家。对于这种具有固定数量级别的递归层次,称为“均衡层次结构”。比如公司之间的关系,每个公司可能存在 个母公司,但可能没有固定的 级、 级等层级关系。对于这种数量级别不固定的递归层次,称为“非均衡层次结构”。

淘宝交易事实表通过叶子类目和类目维表关联,如何统计类目 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 等于 最近一天的 GMV其使用方便性得到大大提高 ,但存在如下三个方面的问题:

● 针对某类目上钻或下钻之前,必须知道其所属的类目层级,然后才能决定限制哪一级类目。如上述示例,限制一级类目 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)。

假设针对类目 0026579 进行上钻操作,步骤如下:

限制类目表的类目 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: 3226633 。此种处理方式扩展性好,但数据使用较为麻烦。

第二种处理方式也是保持维度主键不变,但将多值属性放在维度的多个属性字段中。比如卖家主营类目,由于卖家店铺中可能同时会销售男装、女装、内衣等,所以卖家主营类目可能有多个,但业务需求是只取根据算法计算得到的 TOP3 。针对此种情况,维度的多值属性字段具体值的数量固定,可以采用多个属性字段进行存储,方便数据统计分析和报表展示。如果多值属性字段具体值的数量不固定,则可以采用预留字段的方式,但扩展性较差。卖家主营类目维度设计如图 10.10 所示。

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

10.4.5 杂项维度

在维度建模中,有 种维度叫 Junk Dimension ,中文一般翻译为“杂项维度\杂项维度是由操作型系统中的指示符或者标志宇段组合而成的,一般不在一致性维度之列。比如淘宝交易订单的交易类型宇段,包括话费充值、司法拍卖、航旅等类型 :支付状态、物流状态等,它们在源系统中直接保存在交易表中。

一个事实表中可能会存在多个类似的字段,如果作为事实存放在事实表中,则会导致事实表占用空间过大 如果单独建立维表,外键关联到事实表,则会出现维度过多的情况;如果将这些字段删除,则会有人不同意。

这时,通常的解决方案就是建立杂项维度 ,将这些字段建立到一个维表中,在事实表中只需保存一个外键即可。多个字段的不同取值组成一条记录,生成代理键,存人维表中,并将该代理键保存到相应的事实表字段下。建议不要直接使用所有的组合生成完整的杂项维表,在抽取遇到新的组合时生成相应的记录即可。杂项维度 ETL 过程比一般维度略微复杂些。

但在阿里巴巴的实践中,杂项维度不仅包含上述指示符、状态或分类等枚举宇段,还包含很多非枚举字段,如交易留言、交易属性(由若干k-v 对组成)、交易标签(由二进制位表示)等。针对这些字段,不可能生成所有的组合 ;同时,由于在分布式计算系统中生成代理键的复杂度,一般在逻辑建模中 ,会使用实体的主键作为杂项维度的主键。只考虑杂项维度,忽略其他维度,如图 10. l 所示

但子订单维度一般是逻辑模型,物理实现时不进行物理化,订单杂项维度和其他维度一起,会将维度属性退化至事实表中,详情在事实表中描述。
注:本章节部分理论来自于 Christopher Adamson Star Schema -The Complete Reference Ralph Kimball The Data Warehouse Toolkit-The Definitive Guide to Dimensional Modeling 本书结合阿里的实践进行讲解,细节内容请参考各自著作进行学习

大数据之路读书笔记-10维度设计相关推荐

  1. 大数据之路读书笔记-16数据应用

    大数据之路读书笔记-16数据应用 全球知名咨询公司麦肯锡称:"数据,已经 透到当今每一个行业和业务职能领域,成为重要的生产要素.人们对于海量数据的挖掘和运用,预示着新一波生产率增长和消费者盈 ...

  2. 大数据之路读书笔记-09阿里巴巴数据整合及管理体系

    大数据之路读书笔记-09阿里巴巴数据整合及管理体系 面对爆炸式增长的数据,如何建设高效的数据模型和体系,对这些数据进行有序和有结构地分类组织和存储,避免重复建设和数据不一致性,保证数据的规范性, 直是 ...

  3. 大数据之路读书笔记-11事实表设计

    大数据之路读书笔记-11事实表设计 文章目录 大数据之路读书笔记-11事实表设计 11.1 事实表基础 11.1.1 事实表特性 11.1.2 事实表设计原则 11.1.3 事实表设计方法 11.2 ...

  4. 大数据之路读书笔记-02日志采集

    大数据之路读书笔记-02日志采集 数据采集作为阿里大数据系统体系的第 环尤为重要.因此阿里巴巴建立了一套标准的数据采集体系方案,致力全面.高性能.规范地完成海量数据的采集,并将其传输到大数据平台.本章 ...

  5. 大数据之路读书笔记-01总述

    大数据之路读书笔记-01总述 此系列文章为大数据之路的读书笔记,如侵可删 2014 年,马云提出,"人类正从 IT 时代走向 DT 时代 "如果说IT时代是以自我控制.自我管理为主 ...

  6. 大数据之路读书笔记-03数据同步

    大数据之路读书笔记-03数据同步 如第一章所述,我们将数据采集分为日志采集和数据库数据同步两部分.数据同步技术更通用的含义是不同系统间的数据流转,有多种不同的应用场景.主数据库与备份数据库之间的数据备 ...

  7. 大数据之路读书笔记-15数据质量

    大数据之路读书笔记-15数据质量 随着 IT向DT 时代的转变,数据的重要性不言而喻,数据的应用也日趋繁茂,数据正扮演着一个极其重要的角色.而对于被日益重视的数据,如何保障其质量也是间里巴巴乃至业界都 ...

  8. 阿里巴巴大数据之路读书笔记——用户画像的定义

    用户画像 在阿里巴巴旗下的淘宝网.虾米音乐上都不乏个性化推荐场景,淘 宝.天猫平台上的众多商家则需要通过用户调研和产品研发来把握产品 的目标人群和人群偏好,从而对用户投其所好.对用户有深刻的理解是 网 ...

  9. 阿里巴巴大数据之路读书分享

    阿里巴巴大数据之路读书分享 文章目录 阿里巴巴大数据之路读书分享 前言 阿里巴巴大数据系统的体系架构图及介绍 数据采集层 数据采集 数据传输 数据计算层 离线数据开发 实时数据开发 数据服务层 数据应 ...

最新文章

  1. 用c语言设计一个菜单界面_用这7个方法设计菜单,让餐厅的利润暴涨
  2. Flume-0.9.4数据插入HBase-0.96
  3. SAP MM初阶事务代码MEK1维护PB00价格
  4. [EULAR文摘] 肢端MRI能否在未分化关节患者中甄别出RA患者
  5. [转]颠覆式前端UI开发框架:React
  6. Github项目解析(九)--实现Activity跳转动画的五种方式
  7. cocos2d的常用动作及效果总结之五:Animation
  8. js如何把ajax获取的值返回到上层函数里?
  9. Java逆向基础之AspectJ的获取成员变量的值
  10. qtp如何连接mysql_QTP连接MYSQL数据库方法
  11. AlexNet原理及tensorflow实现
  12. 2021-2025年中国成人脊柱矫形器行业市场供需与战略研究报告
  13. vue中的自定义分页插件组件
  14. ps分辨率像素英寸和厘米的区别_南南带你免费学习超级强大的做图软件-PS(第一章:第二节)...
  15. 使用NodeJS调用Dubbo工程
  16. 弱网环境搭建方案选型
  17. rails/ruby/gem/RubyOnRails环境搭建-Windows
  18. 微信企业号已停止提供企业消息会话服务器,企业微信注册时显示会话服务已经被安装了怎么解决 解决攻略教程大全...
  19. 临床数据共享能带来什么好处?
  20. 玩转NVIDIA Jetson AGX Xavier(3)--- 使用JetPack 4.1为Xavier刷机

热门文章

  1. 关于JavaScript编译原理以及作用域的深入探讨
  2. 体验BIO和NIO的区别
  3. Android 蓝牙打印小票与WiFi打印小票两种打印方式的实现(带有图片和二维码)
  4. 计算图像的质心(重心)
  5. PC客户端UI自动化
  6. 微信小程序之多列表的显示和隐藏功能【附源码】
  7. Java学习笔记:使用Word模板简化文件创建
  8. 30个优秀网站源码、编程源码下载网站大集中
  9. IIS Url Rewrite重写不生效
  10. 计算机导论 试用真值表证明下列,离散数学古天龙-1-4章答案