目录
[1. 数仓简介](#1. 数仓简介)
[2. 数仓特点](#2. 数仓特点)
[3. 数据处理类别](#3. 数据处理类别)
[1. 数仓分层分析](#1. 数仓分层分析)
[2. 第一层:ODS](#2. 第一层:ODS)
[3. 第二层:DW](#3. 第二层:DW)
[4. 第三层:APP](#4. 第三层:APP)
[5. 细节补充:事实表、维度表和中间表](#5. 细节补充:事实表、维度表和中间表)
[6. 数仓的数据模型](#6. 数仓的数据模型)
[6-1 星状模型](#6-1 星状模型)
[6-2 雪花状模型](#6-2 雪花状模型)
[6-3 星座模型](#6-3 星座模型)
[6-4 星型与雪花状对比](#6-4 星型与雪花状对比)
[3-1 HiveQL](#3-1 HiveQL)
[3-2 Hive与MySQL对比](#3-2 Hive与MySQL对比)
[1. 基本数据类型](#1. 基本数据类型)
[2. 集合数据类型](#2. 集合数据类型)
一、数据仓库及其特点
1. 数仓简介
数据仓库,英文名称为:Data WareHouse,可以简写为DW(或DWH)。数据仓库的目的是为了构建面向分析的集成化数据环境,为组织或企业提供决策支持。
数据仓库的定义:数据仓库是一个面向主题的(subject-oriented)、数据集成的(integrated)、非易失的(non-volatile)和时变的(time-variant)数据集合。
数据仓库模型设计的方法论很多,著名的是两种:范式建模 和维度建模
- 范式建模:一种自上而下的方法,将数据组织成规范化的表格,维护数据的完整性和准确性
- 维度建模:一种自下而上的方法,将数据组织成面向主题的维度表和事务表
数据仓库模型包括星型模型、雪花模型和星座模型,都是以维度进行建模(维度建模)
2. 数仓特点
-
数据仓库是面向主题的
- 数据仓库是以需求分析为导向,对数据进行组织并划分若干各主题
- 补充:数据库应用是以业务流程为导向,划分为应用程序与数据库
-
数据仓库是数据集成的
- 通过多种维度对指标进行分析
-
数据仓库是非易失的
- 一次写入,多次读取,不建议更新(对于原始数据而言)
-
数据仓库是时变的
- 数据仓库存储的是历史数据,历史数据是随时间不断变化的
- 添加新数据:每年的销售数据会根据一定规则添加到数据仓库
- 删除过期数据:数据仓库中有时会保留很久之前的数据(过去5~10年),但也有过期时间,到过期时间后会删除或转移至更大的数据库内
- 对历史明细数据进行聚合:每天统计的数据可以聚合为每周统计的数据(累加一周的天统计数据即可)
- 数据仓库存储的是历史数据,历史数据是随时间不断变化的
3. 数据处理类别
数据处理类别大致分为两类:联机事务处理 OLTP (Online-Transaction Processing)和联机分析处理 OLAP(Online-Analysis Processing)。
- OLTP 联机事务处理,也称为面向交易的处理过程,是传统关系型数据库的主要应用
- 特征:客户端产生的数据可以立即传送到服务器,服务器进行计算并将计算结果及时反馈给客户端,是对用户操作快速响应的方式之一。(言辞存在局限性,以B/S架构举例的)
- 特点:事务操作频繁,数据量小
- OLAP 联机分析处理,也称为决策支持系统(DSS),是数据仓库系统的主要应用
- 特征:支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。(没有事务性操作)
- 特点:查询操作频繁,数据量大
对比项 | OLTP | OLAP |
---|---|---|
用户 | 操作人员、底层管理人员 | 决策人员、高级管理人员 |
功能 | 日常操作处理 | 分析决策 |
DB设计 | 基于ER模型,面向应用 | 星状/雪花模型,面向主题 |
DB规模 | GB~TB | ≥TB |
数据 | 最新的、细节的、二维的、分立的 | 历史的、聚集的、多维度、集成的 |
存储规模 | 读写数条(甚至数百条)记录 | 读取上百万条(甚至上亿条)记录 |
操作频度 | 非常频繁(以秒计) | 比较宽松(以小时甚至周计) |
工作单元 | 严格的事务 | 复杂的查询 |
用户数(使用的) | 数百个至数千万个 | 数个至数百个 |
度量 | 事务吞吐量 | 查询吞吐量、响应时间 |
二、数仓分层结构
作为数据的规划者,都希望数据能够有序地流转,数据的整个生命周期能够清晰明确地被设计者和使用者感知到。
1. 数仓分层分析
首先,源数据层(ODS)采集并存储的数据来源于不同的数据源,例如点击流数据、数据库数据及文档数据等;然后,通过ETL(Extract-Transform-Load,抽取-转换-加载)将清洗和转换后的数据装载到数据仓库层(DW);最终,数据应用层(APP)根据实际业务需求获取数据仓库层的数据实现报表展示、数据分析或数据挖掘等操作。
2. 第一层:ODS
源数据层(ODS)存储的数据是数据仓库的基础数据,该层存储的数据抽取自不同的数据源,抽取的这些数据通常会进行诸如去噪、去重、标准化等一些列转换操作后才会加载到源数据层。当然,也可以不经过任何处理直接将数据存储到源数据层(根据你的实际数据结构类型而定)。
3. 第二层:DW
数据仓库层(DW)存储的数据是对源数据层中数据的轻度汇总。轻度汇总就是按照一定的主题去组合这些数据。数据仓库层从上而下,又可以细分为明细层(DWD)、中间层(DWM)和业务层(DWS),具体如下:
- 明细层(DWD):根据业务需求对源数据层的数据进行进一步转换。(数据粒度还是不变的)
- 中间层(DWM):在明细层的基础上,对数据做一些轻微的聚合操作,生成一些列中间表。(提高公共指标的复用性)
- 业务层(DWS):在明细层和中间层的基础上,对某个主题的数据进行汇总,其主要用于为后续的数据应用层提供查询服务。(生成宽表)
4. 第三层:APP
数据应用层的数据可以来源于明细层,也可以来源于业务层,或者是两者混合的数据。数据应用层的数据主要是提供给数据分析、数据挖掘、数据可视化等实际业务场景使用的数据。
5. 细节补充:事实表、维度表和中间表
-
事实表
- 对分析主题的度量
- 通常是数值类型
-
维度表
- 包含事实表中事实记录的特性
- 维度是对数据进行分析时特有的一个角度,站在不同角度看待问题,会有不同的结果
-
中间表
- 用于存储中间计算结果的数据表
6. 数仓的数据模型
在数据仓库建设中,一般会围绕星状模型和雪花状模型来设计数据模型。
6-1 星状模型
星状模型由一个事实表和一组维度表组成,并且以事实表为中心,所有的维度表直接与事实表相连 。事实表与维度表之间通过主键外键相关联,维度之间不存在关联关系,当所有维度都关联事实表时,整个图形很像一个星星结构,所以就称之为星型模型。
星状模型是最简单最常用的模型。星状模型本质是一张大表,相比于其他数据模型更适合于大数据处理。(其他模型也可以通过一定的转换,变为星型模型)
缺点:存在一定程度的数据冗余。因为其维度表只有一个层级,有些信息将会被多次存储。比如一张包含国家、省份、城市三列的维度表,国家列会显示很多重复信息。
6-2 雪花状模型
当一个或多个维度表没有直接连接到事实表上,而是通过其他维度表连接到事实表上时,其图解就像多个雪花连接在一起,故称雪花状模型。雪花状模型是对星状模型的扩展。它是对星状模型的维度进一步层次化,原有的各维度表可能被扩展为小的事实表,形成一些局部的"层次"区域,这些被分解的表都连接到主维度表而不是事实表。
优点:通过最大限度地减少数据存储量以及联合较小的维度表来改善查询销量,避免了数据冗余。
缺点:增加了主键-外键关联,导致查询效率低于星状模型,不利于开发。
6-3 星座模型
星座模型也是星型模型的扩展。区别是星座模型中存在多张事务表,不同事务表之间共享维度表信息,常用于数据关系更复杂的场景。
6-4 星型与雪花状对比
属性 | 星型模型(星座模型) | 雪花模型 |
---|---|---|
事实表 | 1张或多张 | 1张或多张 |
维度表 | 一级维表 | 多层级维表 |
数据总量 | 多 | 少 |
数据冗余度 | 高 | 低 |
可读性 | 高 | 低 |
表个数 | 少 | 多 |
表宽度 | 宽 | 窄 |
查询逻辑 | 简单 | 复杂 |
查询性能 | 高 | 低 |
扩展性 | 差 | 好 |
三、Hive概述
3-1 HiveQL
Hive是基于Hadoop的数据仓库工具,主要用来对数据进行抽取、转换和加载操作 。Hive定义了简单的类SQL查询语言,称为HiveQL ,它可以将结构化的数据文件映射成一张数据表,允许熟悉SQL的用户查询数据,也允许熟悉MapReduce的开发者开发自定义的mapper和reducer来处理内建的mapper和reducer无法完成的复杂的分析工作。
虽然Hive采用类SQL的查询语言HiveQL,但是Hive不是数据库,Hive不实际存放永久数据,它只是有元数据存储系统(MetaStore)并通过HiveQL来处理数据。
3-2 Hive与MySQL对比
对比项 | Hive | MySQL |
---|---|---|
查询语言 | HiveQL | SQL |
数据存储位置 | HDFS | 块设备、本地文件系统 |
数据格式 | 用户定义 | 系统决定 |
数据更新 | 支持(Hive0.14开始) | 支持 |
事务 | 支持(Hive0.14开始) | 支持 |
执行延迟 | 高 | 低 |
可扩展性 | 高 | 低 |
数据规模 | 大 | 小 |
多表插入 | 支持 | 不支持 |
四、Hive架构
Hive是底层封装了Hadoop的数据仓库处理工具,其运行在Hadoop基础之上。Hive架构组成主要包含4个部分,分别是用户接口 、跨语言服务 、驱动引擎 以及元数据存储系统。
-
用户连接接口(CLI、JDBC、Web UI)
- CLI:是指Shell命令行
- JDBC/ODBC:是指Hive的java实现,与传统数据库JDBC类似
- Web UI:是指可通过浏览器访问Hive
-
ThriftServer - 跨语言服务
- hive的可选组件,此组件是一个软件框架服务,允许客户端使用包括Java、C++、Python或其他很多种语言通过编程的方式远程访问Hive
-
MetaStore - 元数据存储系统
- Hive 本身并不直接存储数据,而是通过元数据来描述数据在底层文件系统中的位置和结构
- 元数据存储在关系型数据库中Derby(内置的数据库),也可以配置元数据存储在MySQL中
- Hive中的元数据包括:表名、表所属的数据库名、 表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等
-
Driver - 驱动器
- 解析器(SQLParser): 将HiveQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库(Antlr)完成对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误
- 编译器(Compiler):将 HiveQL 语句解析成抽象语法树(AST),并将 AST 转换为逻辑计划
- 优化器(Optimizer):对逻辑计划进行优化(谓词下推、列裁剪、连接优化等),生成物理计划(Physical Plan),选择合适的执行引擎(如MapReduce、Tez、Spark)
- 执行器(Executer):执行引擎根据物理计划进行实际的数据处理,将结果返回给用户
五、Hive工作流程
Hive利用Hadoop的HDFS存储数据,利用Hadoop的MapReduce执行查询。
(1)CLI(命令行)将用户提交的HiveQL语句发送给DRIVER(驱动器);
(2)DRIVER(驱动器)将HiveQL语句发送给COMPILER(编译器)获取执行计划;
(3)COMPILER(编译器)从METASTORE(元数据存储系统)获取HiveQL语句所需的元数据;
(4)METASTORE(元数据存储系统)将查询到的元数据信息发送给COMPILER(编译器);
(5)COMPLIER(编译器)得到元数据后,
- 首先将HiveQL语句转换(使用第三方库Antlr)为抽象语法树(AST)
- 然后将抽象语法树(AST)转化为查询块,接着将查询块转换为逻辑执行计划,
- 最后将逻辑计划转换为物理执行计划(Physical Plan),并将物理执行计划解析为MapReduce任务发送给DRIVER(驱动器)
(6)DRIVER(驱动器)将MapReduce任务发送给EXECUTION ENGINE(执行引擎)执行,
-
EXECUTION ENGINE(执行引擎)接收到MapReduce任务后,
-
首先从METASTORE获取元数据,然后将元数据写入到HDFS,
-
接着将MapReduce任务提交到ResourceManager,
-
ResourceManager接收到MapReduce任务后,将其分配到指定的NodeManager去执行,
-
NodeManager执行任务时会向NameNode发送读写请求获取相关数据以及写入临时文件的结果文件,
-
最后ResourceManager返回MapReduce任务的执行信息;
(7)CLI向DRIVER发送获取HiveQl语句执行结果的请求;
(8)DRIVER(驱动器)与EXECUTION ENGING(执行引擎)进行通信,请求获取HiveQL语句执行结果的请求;
(9)EXECUTION ENGING(执行引擎)向NameNode发送请求获取HiveQL语句执行结果的请求,NameNode获取到HiveQL语句的执行结果后,会将执行结果返回EXECUTION ENGING(执行引擎),EXECUTION ENGING(执行引擎)将执行结果返回DRIVER(驱动器),最终DRIVER(驱动器)将执行结果返回CLI。
六、Hive数据类型
1. 基本数据类型
数据类型 | 描述 | 了解 |
---|---|---|
tinyint | 1字节有符号整数 | (-128 到 127) |
smallint | 2字节有符号整数 | (-32768 到 32767) |
int/integer | 4字节有符号整数 | (-2147483648 到 2147483647) |
bigint | 8字节有符号整数 | 范围非常大,可以表示极大的整数数值 |
float | 4字节单精度浮点数 | 最小正非规格化数2-149,最大规格化数约为2128 - 2104 |
double | 8字节双精度浮点数 | 最小正非规格化数2-1074,最大规格化数为21024 - 2971 |
double precision | 8字节双精度浮点数 | 和double等价,从Hive2.2.0提供 |
decimal | 高精度浮点数 | decimal(precision,scale)默认precision(最大位数)10,scale(小数点后位数)0 |
numeric | 高精度浮点数 | 同decimal,Hive3.0开始提供 |
timestamp | 精度到纳秒 | unix时间戳(从 1970 年 1 月 1 日 00:00:00 UTC(协调世界时)起至特定时间点经过的秒数) |
date | YYYY-MM-DD | 以年/月/日形式描述的日期 |
interval | 时间间隔 | interval '1' day 表示间隔一天 |
string | 字符串 | 没有长度限制 |
varchar | 变长字符串 | 字符串长度限制区间为1~65335。如:char(30),插入20个字符时,只会占用20的字符位置 |
char | 定长字符串 | 如:char(30),插入20个字符时,会占用30的字符位置,剩余的空格填充 |
boolean | 布尔值 | true或false |
binary | 字节数组 | 存储加密数据、存储二进制文件内容、与外部系统交互 |
2. 集合数据类型
数据类型 | 描述 |
---|---|
array | array是一组具有相同数据类型元素的集合,array中的元素是有序的,每个元素都有一个编号,编号从0开始,因此可以通过指定位置来获取array中的元素 |
map | map是一种键值对形式的集合,通过key(键)来快速检索value(值)。在map中,key是唯一的,value可以重复 |
struct | struct和c语言中的struct或者"对象"类似,都可以通过"点"符号访问元素内容,元素的数据类型可以不相同 |
-
array(数组)类型举例
CREATE TABLE sales_table (
order_id INT,
products ARRAY<STRING>
);-- 插入数据
INSERT INTO sales_table VALUES
(1, array('product1', 'product2', 'product3')),
(2, array('product4', 'product5'));-- 查询数据
SELECT order_id, products FROM sales_table;-- 查询特定订单中的产品数量
SELECT order_id, size(products) AS product_count FROM sales_table;-- 查询包含特定产品的订单
SELECT order_id FROM sales_table WHERE array_contains(products, 'product2'); -
map(映射)类型举例
CREATE TABLE employee_table (
employee_id INT,
attributes MAP<STRING, STRING>
);-- 插入数据
INSERT INTO employee_table VALUES
(1, map('name', 'John', 'department', 'Sales', 'age', '30')),
(2, map('name', 'Alice', 'department', 'HR', 'age', '25'));-- 查询数据
SELECT employee_id, attributes FROM employee_table;-- 查询特定员工的某个属性值
SELECT employee_id, attributes['name'] AS employee_name FROM employee_table;-- 查询具有特定属性值的员工
SELECT employee_id FROM employee_table WHERE attributes['department'] = 'Sales'; -
struct(复合数据)类型举例
CREATE TABLE log_table (
log_id INT,
log_info STRUCT<log_date:STRING, log_time:STRING, user_id:INT, operation:STRING>
);-- 插入数据
INSERT INTO log_table VALUES
(1, named_struct('log_date', '2024-10-17', 'log_time', '10:30:00', 'user_id', 123, 'operation', 'login')),
(2, named_struct('log_date', '2024-10-17', 'log_time', '11:15:00', 'user_id', 456, 'operation', 'logout'));-- 查询数据
SELECT log_id, log_info.log_date, log_info.log_time, log_info.user_id, log_info.operation FROM log_table;