数据仓库

英文名称为==Data Warehouse==,可简写为DW或DWH。数据仓库的目的是==构建面向分析的集成化数据环境==,为企业提供==决策支持==(Decision Support)。它出于分析性报告和决策支持目的而创建。

数据仓库本身并不“生产”任何数据,同时自身也不需要“消费”任何的数据,数据来源于外部,并且开放给外部应用,这也是为什么叫“仓库”,而不叫“工厂”的原因。

定义

数据仓库是==面向主题的==(Subject-Oriented )、==集成的==(Integrated)、==稳定性的==(Non-Volatile)和==时变的==(Time-Variant )数据集合,用以支持管理决策。

面向主题

数据仓库中的数据是按照一定的主题域进行组织。

主题是一个抽象的概念,是指用户使用数据仓库进行决策时所关心的重点方面,一个主题通常与多个操作型信息系统相关。

以电商为例:

用户主题:主要是用于分析用户的行为

商品主题:针对商品进行分析 指标:昨日新增商品,昨日下架商品 最近七天流量最高的哪些商品

财务主题:财务分析

订单主题:订单分析

货运主题:针对快递分析

集成性

根据决策分析的要求,将分散于各处的源数据进行抽取、筛选、清理、综合等工作,最终集成到数据仓库中。

稳定性

数据的相对稳定性,数据仓库中的数据只进行新增,没有更新操作、删除操作处理。

反映历史变化,以查询分析为主。

时变性

数据仓库的数据一般都带有时间属性,随着时间的推移而发生变化,不断地生成主题的新快照

数据仓库与数据库的区别

数据库与数据仓库的区别实际讲的是 OLTP 与 OLAP 的区别。

==OLTP==: On-Line Transaction Processing 叫==联机事务处理==, 也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理 .

==OLAP==:On-Line Analytical Processing 叫==联机分析处理==,一般针对某些主题的历史数据进行分析,支持管理决策。

简而言之,==数据库是面向事务的设计,数据仓库是面向主题设计的==。

数据库一般存储在线交易数据,有很高的事务要求;数据仓库存储的一般是历史数据。

数据库设计是尽量避免冗余,一般采用符合范式的规则来设计,数据仓库在设计是有意引入冗余,采用反范式的方式来设计。

数据库是==为捕获数据而设计==,数据仓库是==为分析数据而设计==,它的两个基本的元素是维表和事实表。维是看问题的角度,比如时间,部门,维表放的就是这些东西的定义,事实表里放着要查询的数据,同时有维的ID。

功能 数据仓库 数据库
数据范围 存储历史的、完整的、反应历史变化的 当前状态数据
数据变化 可添加、无删除、无变更的、反应历史变化 支持频繁的增、删、改、查操作
应用场景 面向分析、支持战略决策 面向业务交易流程
设计理论 违范式、适当冗余 遵照范式(第一、二、三等范式)、避免冗余
处理量 非频繁、大批量、高吞吐、有延迟 频繁、小批次、高并发、低延迟

构建数据仓库

• 传统数仓建设更多的基于成熟的商业数据集成平台,比如Teradata、Oracle、Informatica等,技术体系比较成熟完善,但相对比较封闭,对实施者技术面要求也相对专业且单一,一般更多应用于银行、保险、电信等“有钱”行业.

• 基于大数据的数仓建设一般是基于非商业、开源的技术,常见的是基于hadoop生态构建,涉及技术较广泛、复杂,同时相对于商业产品,稳定性、服务支撑较弱,需要自己维护更多的技术框架。在大数据领域,==常用的数据仓库构建手段很多基于hive,sparkSQL,impala等各种技术框架==.

仓库分层

数据仓库分层描述

  • 数据仓库更多代表的是一种对数据的管理和使用的方式,它是一整套包括了etl、调度、建模在内的完整的理论体系。现在所谓的大数据更多的是一种数据量级的增大和工具的上的更新。 两者并无冲突,相反,而是一种更好的结合。数据仓库在构建过程中通常都需要进行分层处理。业务不同,分层的技术处理手段也不同。
  • 分层是数据仓库解决方案中,数据架构设计的一种数据逻辑结构 ,通过分层理念建立的数据仓库,它的可扩展性非常好,这样设计出来的模型架构,可以任意地增减、替换数据仓库中的各个组成部分。

从整体的逻辑划分来讲,数据仓库模型实际上就是这三层架构。

接入层:底层的数据源或者是操作数据层,一般在公司的话,统一都是称为ODS层

中间层:是做数据仓库同学需要花费更多精力的一层,这一层包括的内容是最多的、最复杂的。

应用层:对不同的应用提供对应的数据。该层主要是提供数据产品和数据分析使用的数据,
       比如我们经常说的报表数据

  • 针对于这三层架构,这里给出比较典型的一个做数据仓库在实施的时候,具体的层次划分。

dw

  • ==ODS==:

    • Operation Data Store 原始数据层
  • ==DWD==

  • data warehouse detail 数据明细层

  • 它主要是针对于接入层的数据进行数据的清洗和转换。还有就是一些维度的补充。

  • ==DWS==

    • data warehouse summary 数据汇总层

    • 它是在DWD明细层之上,也有公司叫DW层

    • 它是按照一定的粒度进行了汇总聚合操作。它是单业务场景。

  • ==DWM==

  • data warehouse market 数据集市层

    • 它是在DWS数据汇总层之上,集市层它是多业务场景的。
  • ==APP==

    • Application 应用层
    • 这个是数据仓库的最后一层数据,为应用层数据,直接可以给业务人员使用
TMP临时表:在做一些中间层表计算的时候,大量使用tmp临时表。
DIM维度层:基于ODS层和DWD层抽象出一些公共的维度,
          典型的公共维度主要包括城市信息、渠道信息、个人基础属性信息。

为什么要进行数据仓库分层

  • 分层的主要原因是在管理数据的时候,能对数据有一个更加清晰的掌控,主要有下面几个原因:
    • 空间换时间
      • 通过建设多层次的数据模型供用户使用,避免用户直接使用底层操作型数据,可以更高效的访问数据。
    • 把复杂问题简单化
      • 讲一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性,当数据出现问题之后,可以不用修复所有的数据,只需要从有问题的步骤开始修复。
    • 便于处理业务的变化
      • 随着业务的变化,只需要调整底层的数据,对应用层对业务的调整零感知。

数据仓库建模

​ 目前业界较为流行的数据仓库的建模方法非常多,这里主要介绍==范式建模法==,==维度建模法==,==实体建模法==等几种方法,每种方法其实从本质上讲就是从不同的角度看我们业务中的问题,不管从技术层面还是业务层面,其实代表的是哲学上的一种世界观。

范式建模法(Third Normal Form 3NF)

范式建模法是基于整个关系型数据库的理论基础之上发展而来的,其实是我们在构建数据模型常用的一个方法,主要解决关系型数据库得数据存储,利用的一种技术层面上的方法。目前,我们在关系型数据库中的建模方法,大部分采用的是三范式建模法。

从其表达的含义来看,一个符合第三范式的关系必须具有以下三个条件 :

(1)每个属性值唯一,不具有多义性 ;
(2)每个非主属性必须完全依赖于整个主键,而非主键的一部分 ;
(3)每个非主属性不能依赖于其他关系中的属性,因为这样的话,这种属性应该归到其他关系中去。

维度建模法

维度建模(dimensional modeling)是专门用于分析型数据库、数据仓库、数据集市建模的方法。维度建模法简单描述就是按照事实表、维度表来构建数仓、集市。
维度建模从分析决策的需求出发构建模型,为分析需求服务,因此它重点关注用户如何更快速地完成需求分析,同时具有较好的大规模复杂查询的相应性能。

  • 维度表
维度表示你要对数据进行分析时所用的一个量,比如你要分析产品销售情况, 
你可以选择按类别来进行分析,或按区域来分析。

通常来说维度表信息比较固定,且数据量小
  • 事实表
表示对分析主题的度量。
事实表包含了与各维度表相关联的外键,并通过join方式与维度表关联。事实表的度量通常是数值类型,且记录数会不断增加,表规模迅速增长。

消费事实表:Prod_id(引用商品维度表), TimeKey(引用时间维度表), Place_id(引用地点维度表), Unit(销售量)。
总的说来,在数据仓库中不需要严格遵守规范化设计原则。因为数据仓库的主导功能就是面向分析,以查询为主,不涉及数据更新操作。事实表的设计是以能够正确记录历史信息为准则,维度表的设计是以能够以合适的角度来聚合主题内容为准则
维度建模三种模式

基于事实表和维表就可以构建出多种多维模型,包括星形模型、雪花模型和星座模型。

维度建模法最被人广泛知晓的名字就是星型模式。

  • ==星型模式==

    星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为
    中心,所有的维度表直接连接在事实表上,像星星一样。
    星形模式的维度建模由一个事实表和一组维表成,且具有以下特点:
    a. 维表只和事实表关联,维表之间没有关联;
    b. 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键;
    c. 以事实表为核心,维表围绕核心呈星形分布;
    
    

    星型模型

  • ==雪花模式==
雪花模式是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能也比星型模型要低。所以一般不是很常用。

雪花模型

  • ==星座模式==
星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。

前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式。

星座模型

实体建模法

实体建模法并不是数据仓库建模中常见的一个方法,它来源于哲学的一个流派。

从哲学的意义上说,客观世界应该是可以细分的,客观世界应该可以分成由一个个实体,以及实体与实体之间的关系组成。

那么我们在数据仓库的建模过程中完全可以引入这个抽象的方法,将整个业务也可以划分成一个个的实体,而每个实体之间的关系,以及针对这些关系的说明就是我们数据建模需要做的工作。

参考文档:http://www.uml.org.cn/sjjmck/201810163.asp

数据仓库架构

  • ==数据采集==
数据采集层的任务就是把数据从各种数据源中采集和存储到数据存储上,期间有可能会做一些ETL操作。

数据源种类可以有多种:
日志:所占份额最大,存储在备份服务器上
业务数据库:如Mysql、Oracle
来自HTTP/FTP的数据:合作伙伴提供的接口
其他数据源:如Excel等需要手工录入的数据
  • ==数据存储与分析==
HDFS是大数据环境下数据仓库/数据平台最完美的数据存储解决方案。

离线数据分析与计算,也就是对实时性要求不高的部分,Hive是不错的选择。
使用Hadoop框架自然而然也提供了MapReduce接口,如果真的很乐意开发Java,或者对SQL不熟,那么也可以使用MapReduce来做分析与计算。
Spark性能比MapReduce好很多,同时使用SparkSQL操作Hive。
  • ==数据共享==
  前面使用Hive、MR、Spark、SparkSQL分析和计算的结果,还是在HDFS上,但大多业务和应用不可能直接从HDFS上获取数据,那么就需要一个数据共享的地方,使得各业务和产品能方便的获取数据。

  这里的数据共享,其实指的是前面数据分析与计算后的结果存放的地方,其实就是关系型数据库和NOSQL数据库。
  • ==数据应用==
报表:报表所使用的数据,一般也是已经统计汇总好的,存放于数据共享层。
接口:接口的数据都是直接查询数据共享层即可得到。
即席查询:即席查询通常是现有的报表和数据共享层的数据并不能满足需求,需要从数据存储层直接查询。一般都是通过直接操作SQL得到。

数据倾斜

由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点
在执行任务的时候,任务进度长时间维持在99%左右,查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大。

单一reduce的记录数与平均记录数差异过大,通常可能达到3倍甚至更多。最长时长远大于平均时长。

450330742

原因

1)、key分布不均匀

2)、业务数据本身的特性

3)、建表时考虑不周

4)、某些SQL语句本身就有数据倾斜

解决方案

map端聚合

--Map 端部分聚合,相当于Combiner
hive.map.aggr = true;
--有数据倾斜的时候进行负载均衡
hive.groupby.skewindata=true;

--有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

SQL语句调节

  • 如何Join

    关于驱动表的取,用join key分布最均匀的表作为驱动表
    做好列裁剪和filter操作,以达到两表做join的时候,数据量相对变小的效果。
    
  • 大小表Join

    使用map join让小的维度表(1000条以下的记录条数) 先进内存。在map端完成reduce.
    
  • 大表Join大表

    把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
    
  • count distinct大量相同特殊值

    count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。
    
  • group by维度过小

    采用sum() group by的方式来替换count(distinct)完成计算。
    
  • 特殊情况特殊处理

    在业务逻辑优化效果的不大情况下,一些时候是可以将倾斜的数据单独拿出来处理。最后union回去
    

业务场景

  • 空值产生的数据倾斜

    • 场景

      如日志中,常会有信息丢失的问题,比如日志中的 user_id,如果取其中的 user_id 和 用户表中的user_id 关联,会碰到数据倾斜的问题。
      
    • 解决办法

    ~~~sql
    –user_id为空的不参与关联

    select from log a
    join users b
    on a.user_id is not null
    and a.user_id = b.user_id
    union all
    select
    from log a
    where a.user_id is null;

–赋与空值分新的key值
select *
from log a
left outer join users b
on case when a.user_id is null then concat(‘hive’,rand()) else a.user_id end = b.user_id;


* 不同数据类型关联产生数据倾斜

  * 场景

用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时,默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。


  * 解决办法

    * 把数字类型转换成字符串类型

    ~~~sql
    select * from users a
      left outer join logs b
      on a.usr_id = cast(b.user_id as string);