数据仓库面试题
1.数据仓库的概念 ⭐️
简单点来说,现实情况是一个企业有很多数据源,比如有的业务数据存放在Mysql,PG库,有的存放在Oracle,有的日志存放在Ftp,Nginx服务器上等,有的是外部采集的爬虫数据等等。
那么对于企业来说沉淀了这么多数据,如何将这些数据放到一起进行数据融合,数据分析,给企业挖掘数据价值呢?这些不同数据源,不同数据存储格式,不同的数据更新周期,如果让你把企业这些数据融合分析,你怎么办?
首先,你是不是要把这些不同数据按照统一的格式,一定的规范存储到一起,然后在通过特定的工具做数据计算分析?那么对于企业来说,把企业不同各种数据源的数据放到一起存储和计算的地方就叫数据仓库(约定俗称的叫法),所以本质上数据仓库上融合各个数据源,存储加工数据的地方,并且为企业各部门提供一个统一规范的数据出口,供企业决策使用。
数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
数据源有三类
- 结构化:以便是标准数据库,比如MySQL
- 半结构化:日志文件,以JSON或者XML形式存在
- 非结构化:图片、视频、音频等
2.数据仓库和数据库的区别 ⭐️⭐️
数据库:主要用于事务处理,即OLTP(Transaction),用户使用数据库关心的是数据的完整性、安全性、并发等一些问题,并且数据库一般是读写优化,但是在读大量数据方面是支持不足的。
数据仓库:主要用于数据分析,即OLAP(Analytics),供上层决策,常见于一些查询性的统计数据,一般是读优化的。
3.ETL ⭐️
抽取:这个环节可能主要是比如说Sqoop、Flume、Kafka、还有Kettle、DataX、Maxwell这些都是抽取工具。离线可能主要是用的Sqoop或者是DataX去进行离线数据的抽取,像实时可能会采用比如说Flume或者是Kafka、Maxwell,还有Kettle去进行抽取。
转换:转换包括清洗、合并、拆分、加工等等,可以用Hadoop生态的东西, MapReduce、Spark、Flink、Hive等去进行数据方面的清洗。
加载:抽取转换之后,就是将数据加载到目标数据库。可能会用到Hbase去存储一些大数据方面的东西,或者HDFS等等这些工具。
4.数仓为什么分层 ⭐️⭐️⭐️
①清晰数据结构:
每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。
②方便数据血缘追踪:
简单来说,我们最终给业务呈现的是一个能直接使用业务表,但是它的来源有很多,如果有一张来源表出问题了,我们希望能够快速准确地定位到问题,并清楚它的危害范围。
③减少重复开发:
规范数据分层,开发一些通用的中间层数据,能够减少极大的重复计算。
④把复杂问题简单化(解耦):
将一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性,当数据出现问题之后,可以不用修复所有的数据,只需要从有问题的步骤开始修复。
5.数仓每一层的作用 ⭐️⭐️⭐️
ODS(Operational Data Store)
数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的 ETL 之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。
一般来讲,为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可,至于数据的去噪、去重、异常值处理等过程可以放在后面的DWD层来做。
DW(Data Warehouse):数据仓库层
- DWD(Data Warehouse Detail):数据明细层
该层一般保持和ODS层一样的数据粒度,并且提供一定的数据质量保证。同时,为了提高数据明细层的易用性,该层会采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联。
另外,在该层也会做一部分的数据聚合,将相同主题的数据汇集到一张表中,提高数据的可用性。
- DWM(Data Warehouse Middle):数据中间层
该层会在DWD层的数据基础上,对数据做轻度的聚合操作,生成一系列的中间表,提升公共指标的复用性,减少重复加工。直观来讲,就是对通用的核心维度进行聚合操作,算出相应的统计指标。 - DWS(Data Warehouse Service):数据服务层
又称数据集市或宽表。按照业务主题划分,如流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。
一般来讲,该层的数据表会相对比较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。在实际计算中,如果直接从DWD或者ODS计算出宽表的统计指标,会存在计算量太大并且维度太少的问题,因此一般的做法是,在DWM层先计算出多个小的中间表,然后再拼接成一张DWS的宽表。由于宽和窄的界限不易界定,也可以去掉DWM这一层,只留DWS层,将所有的数据在放在DWS亦可。
ADS/APP/DM:数据应用层/数据集市
在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、PostgreSql、Redis等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。比如我们经常说的报表数据,一般就放在这里。
DIM(Dimension):维表层
维表层主要包含两部分数据:
高基数维度数据:一般是用户资料表、商品资料表类似的资料表。数据量可能是千万级或者上亿级别。
低基数维度数据:一般是配置表,比如枚举值对应的中文含义,或者日期维表。数据量可能是个位数或者几千几万。
6.事实表与维度表 ⭐️⭐️⭐️
6.1 三种事实表
-
事实表:每一个操作型事件,都会产生可度量的值,就会产生事实表,事实表主要储存事实的度量以及指向各个维的外键值
- 事务型事实表
以每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。每一行的粒度代表实体的一个事务
- 周期型快照事实表
它统计的是间隔周期内的度量统计。每一行的粒度是某时间周期内的一个实体
- 累积型快照事实表
累计快照事实表用于跟踪业务事实的变化。每行代表一个实体的生命周期
-
维度表:维度的描述信息,描述某个客观存在的事物的属性
-
宽表:通常是指业务主题相关的指标、维度、度量关联在一起的一张数据库表。由于把不同的内容都放在同一张表存储,宽表已经不符合三范式的模型设计规范,随之带来的主要坏处就是数据的大量冗余,与之相对应的好处就是查询性能的提高与便捷
-
窄表:严格按照数据库设计三范式。尽量减少数据冗余,但是缺点是修改一个数据可能需要修改多张表
6.2 事实表和维度表的区别
维度表内容量相对少,变化少
事实表变化程度大,新增多
使用维度表有诸多好处,具体如下:
- 缩小了事实表的大小
- 便于维度的管理和维护,增加、删除和修改维度的属性,不必对事实表的大量记录进行改动
- 维度表可以为多个事实表重用,以减少重复工作
6.3 退化维度
过于简单或诸如订单ID这种量级很大的维度,不值得单独创建一个维表进行存储,直接把一些简单的维度放在事实表中。
支付方式可以创建一个维度表,但完全可以退化到支付事实表中
退化维度优点
1.减少事实表和维度表的关联
2.该技术减少维度的数量, 简化维度数据仓库模式。 简单的模式比复杂的更容易理解, 也有更好的查询性能。
3.可以让group by 等操作变得更快,因为无需关联
6.4 缓慢变化维
维度的属性并不是始终不变的,它会随着时间的流逝发生缓慢的变化,这种随时间发生变化的维度我们一般称之为缓慢变化维(SCD)。比如员工表中的部门维度,员工的所在部门有可能两年后调整一次
缓慢变化维的处理方式
-
1.直接覆盖
修改维度属性为最新值,直接覆盖,操作简单,但不保留历史信息,适用于不关注历史数据的场景。
-
2.增加新行 拉链表 此方式及其变种是处理缓慢变化维的主要技术。
-
3.增加新列
7.数仓建模方法 ⭐️⭐️⭐️
7.1 范式建模(ER建模)
实体、属性、关系
3范式(是什么,以及相关例子要知道)
范式是关系数据库设计中的规范,目的是为了保证数据的逻辑一致性、避免数据冗余和提高数据完整性。
7.2 维度建模
维度建模步骤
(1)选择业务过程
在业务系统中,挑选我们感兴趣的业务线,比如下单业务,支付业务,退款业务,物流业务,一条业务线对应一张事实表。
(2)声明粒度
数据粒度指数据仓库的数据中保存数据的细化程度或综合程度的级别。
声明粒度意味着精确定义事实表中的一行数据表示什么,应该尽可能选择最小粒度,以此来应各种各样的需求。
典型的粒度声明如下:
订单事实表中一行数据表示的是一个订单中的一个商品项。
支付事实表中一行数据表示的是一个支付记录。
(3)确定维度
维度的主要作用是描述业务是事实,主要表示的是“谁,何处,何时”等信息。
确定维度的原则是:后续需求中是否要分析相关维度的指标。例如,需要统计,什么时间下的订单多,哪个地区下的订单多,哪个用户下的订单多。需要确定的维度就包括:时间维度、地区维度、用户维度。
(4)确定事实
此处的“事实”一词,指的是业务中的度量值(次数、个数、件数、金额,可以进行累加),例如订单金额、下单次数等。
在DWD层,以业务过程为建模驱动,基于每个具体业务过程的特点,构建最细粒度的明细层事实表。事实表可做适当的宽表化处理。
事实表和维度表的关联比较灵活,但是为了应对更复杂的业务需求,可以将能关联上的表尽量关联上。
7.3 范式建模和维度建模的优缺点
1.查询性能:
- 范式建模:由于范式化的表需要更多的连接来获取所需的信息,查询可能较慢。
- 维度建模:设计是为了优化查询性能。通过减少连接数,事实表和维度表的结构可以更快速地返回结果,尤其是对于复杂的分析查询。
2.数据冗余:
- 范式建模:这种模型主要目标是减少数据冗余。通过分解数据表并删除重复的信息,范式建模通常能确保每个数据只存储一次。正常化到高范式,例如第三范式,通常可以消除大多数冗余。
- 维度建模:在这种模型中,数据冗余是允许的,甚至是预期的。事实表和维度表设计使得数据重复存储,以提高查询性能。例如,一个产品的名称可能在多个记录中重复,以避免进行复杂的连接操作。
3.数据一致性:
- 范式建模:这种模型通常可以确保较高的数据一致性。由于冗余被消除,数据的更新或插入通常更简单,且不太可能引入不一致性。
- 维度建模:由于数据冗余,有可能出现数据不一致的情况。例如,如果一个维度中的某个属性发生更改,那么可能需要更新多个地方。但是,有一些策略,如缓慢变化维度(SCD)技术,可以帮助管理这些更改。
4.维度分析:
- 范式建模:虽然范式化的模型不是为维度分析设计的,但它们仍然可以支持分析。然而,可能需要复杂的查询或视图来实现。
- 维度建模:这是维度建模的核心,设计就是为了使维度分析变得简单和直接。维度和事实表的结构允许轻松进行切片、切块和钻取分析。
总结:范式建模和维度建模的选择取决于具体应用的需求。对于需要确保数据一致性且不那么关注查询性能的事务处理系统,范式建模可能更为合适。而对于需要高性能查询和复杂分析的数据仓库或BI系统,维度建模可能是更好的选择。
7.4 数据冗余
假设我们使用星型模型,只有一张中心表和一张维度表,如下
事实表: Sales
| Date | Product_ID | Amount |
产品维度表: Product
| Product_ID | Product_Name | Category_Name |
Product表是非范式化的,因为每个产品的分类都直接存储在维度表中。如果有大量同一类别的产品,该类别的名称Category_Name会在Product表中重复多次,存在冗余
而使用雪花模型,可以再分出一张维度表
事实表: Sales
| Date | Product_ID | Amount |
产品维度表: Product
| Product_ID | Product_Name | Category_ID |
分类维度表: Category
| Category_ID | Category_Name |
在此模型中,Product表和Category表通过Category_ID字段连接。分类名称在Category_Name表中只存储一次,从而避免了冗余
但是这样的话Category_ID 不照样是存储了多次吗?
Category_ID 确实在多个产品记录中重复存储了。但这里的关键区别在于我们所说的“数据冗余”一般是指的复杂的、可能占用更多存储空间的数据项,如文本字符串,而不是简单的标识符或引用数字。
在上述例子中:
在星型模型中,复杂的数据项 Category_Name(可能是一个较长的字符串)在多个产品记录中重复存储了。
在雪花模型中,尽管 Category_ID 在多个产品记录中重复,但这只是一个简单的数字或短字符串。实际的分类名称(可能占用更多存储空间)仅在 Category 表中存储一次。
使用引用ID的主要好处是:
通常,数字ID占用的存储空间要比文本字符串小得多。
如果需要更改类别名称(例如,从"Electronics"更改为"Electronic Goods"),则只需在一个地方(Category 表)进行更改,而不是在每个相关的产品记录中进行更改。保持数据的一致性和完整性更为简单和高效。
7.5 维度模型
星型模型:以事实表为中心,所有维度直接关联在事实表上,呈星型分布
- 优点:查询性能好,不需要左外部的连接查询
- 缺点:存在数据冗余
雪花模型:在星型模型的基础上,维度表上又关联了其他维度表
- 减少了数据冗余
- 连接查询多,性能低
星座模型:基于多张事实表,并且共享维度表信息
8.高内聚低耦合思想⭐️
我们常说的高内聚,一般都是功能内聚,只负责一项任务,也就是常说的单一责任原则。模块的内聚反映模块内部联系的紧密程度。一个模块只需做好一件事件,不要过分关心其他任务。比如访客主题,所有的信息都与用户有关,宽表会导致数据冗余,但会带来查询的便捷与查询性能的提升。
模块与模块之间、系统与系统之间的交互,是不可避免的, 但是我们要尽量减少由于交互引起的单个模块无法独立使用或者无法移植的情况发生, 尽可能多的单独提供接口用于对外操作, 这个就是所谓的低耦合。
9.主题域和数据域 ⭐️
主题域:从业务视角对数据分类。通常用于描述数据仓库中一个广泛的功能或业务领域。它可以包含多个相关的主题。
主题:一个主题定义了数据仓库中的一个特定业务过程或事件,它的数据是针对特定业务需求进行设计和优化的。
数据域:从数据视角对数据分类,数据驱动业务,更好的数据赋能业务。数据域更常见于数据治理和数据管理的领域,描述数据的性质和类型。
划分方法:全局的视角来看,先划分出主题域,再接着在主题域里面划分出各个主题,主题域的划分一般比较谨慎,一旦定下来了避免频繁变动,虽然数仓建设是迭代建设的,不能保证一次性初始化好,但我们的主题域划分和主题划分要尽可能地涵盖企业的所有业务,以及在新业务进来时能够无影响地被包含进来和可扩展主题域。
举例:
- 主题域: 销售
- 主题: 电子产品销售
- 主题: 服装销售