吐槽一下,搞大数据的也要建数据仓库。而且无论是传统行业还是现在的互联网公司,都需要对数据仓库有一定的重视,而不是只说自己是大数据专业的。数据仓库更代表一种管理和使用数据的方式。它是一整套包括etl、调度、建模在内的理论体系。所谓大数据,更多的是数据量级的增加和工具的更新。两者并不冲突,相反,是更好的结合。也就是说,单纯的使用Hadoop、Spark、Flume来处理数据,其实也只是学习了几个新的工具而已。这是一个工具,它只是数据仓库中etl的一部分。当然,技术的更新往往会导致一个时代的更迭,比如Hadoop的诞生,深入研究一个大数据组件需要花费大量的时间和精力。但在热潮降温之后,我们应该考虑如何更好地管理和使用自己的数据。对于数据从业者,要时刻注意紧跟技术变革,但要记住数据为王。在追求极致技术的同时,别忘了我们从事的是数据。文章正题结束后,本文主要讲解数据仓库的一个重要部分:如何设计数据层!其他关于数据仓库的内容可以参考其他文章数据仓库。本文对数据分层的讨论适用于以下部分场景,超过此范围的场景或有经验的数据仓库高手无需浪费时间阅读。数据建设才刚刚开始,大部分数据都是经过粗略的数据接入后直接与业务对接的。当数据建设发展到一定阶段,发现数据使用混乱,各种业务直接从原始数据计算。各种重复计算严重浪费计算资源,需要优化性能。文章结构刚开始做数据仓库的时候遇到了很多坑。由于自己资源有限,在接触数据仓库的时候,感觉互联网行业在数据仓库方面的成功经验很少,网上也很难找到比较实用的资料。而且那几本经典书籍理论性太强,折腾起来真是生不如死。幸运的是,现在那个障碍已经过去了,所以我花更多的时间来整理自己的想法,帮助其他朋友避免一些陷阱。为什么要分层?这个问题已经被好几个同学问过了。因此,分层的价值仍需明确。分享经典的数据分层模型,以及每一层数据的作用和处理方式。分享两个数据层的设计,用这两个实际的例子来说明每一层是如何存储数据的。给点建议,不是最好的,但可以作为参考。为什么要分层我们对数据进行分层的主要原因之一是在管理数据时对数据有更清晰的控制。详细来说,主要有以下几个原因:数据结构清晰:每个数据层级都有它的作用域,这样我们在使用表的时候可以更方便的定位和理解。数据沿袭追踪:简单的说,可以理解为我们最终给业务完整性的是一张可以直接使用的业务表,但是它的来源有很多。如果其中一个源表出现问题,我们希望能够快速准确地定位到问题所在,了解其危害范围。减少重复开发:规范数据分层,开发一些通用的中层数据,可以大大减少重复计算。简化复杂的问题。将一个复杂的任务分解成多个步骤来完成,每一层只处理一个步骤,比较简单易懂。而且,便于保持数据的准确性。当数据出现问题时,不需要修复所有数据,只需要从有问题的步骤开始修复即可。屏蔽原始数据的异常。为了屏蔽业务的影响,您需要在不更改业务一次的情况下重新访问数据。数据系统中每个表的依赖关系就像电线的流动。我们都希望它非常规律,易于管理。然而,最终结果主要是第一张图片,而不是第二张。理论如何分层我们从理论上做一个抽象,数据仓库可以分为以下三层,即:数据操作层、数据仓库层和数据产品层。ODS的全称是OperationalDataStore。操作数据存储是“面向主题”的。数据操作层,也叫ODS层,是数据源中离数据最近的一层。数据源中的数据被提取、清洗和传输。也就是传说中的ETL之后,加载到这一层。这一层的数据一般按照源业务系统的分类方式进行分类。例如,该层可能包括的数据表有:人口表(包括每个人的身份证号码、姓名、地址等)、机场登机记录(包括旅客身份证号码、航班号、登机日期、出发城市、等)、银联卡信息表(包括银行卡号、刷卡地点、刷卡时间、卡金额等)、银行账户表(包括银行卡号、持卡人身份证号等)等一系列原件业务数据。这里我们可以看出,这一层的数据也具有鲜明的业务数据库特征,甚至具有一定的关系数据库数据范式的组织形式。但是,此级别的数据不等同于原始数据。源数据加载到这一层时,比如去噪(比如去除明显偏离正常水平的银行卡信息)、去重(比如银行账户信息、公安局人口信息都包含人名,但只保留就一份),脏数据(比如某人的银行卡被盗,十分钟内同时有中国和日本的两张信用卡信息,这就是脏数据),业务抽取,单位统一,Cut字段(例如用于支持前端系统工作但在数据挖掘中不需要的字段)、业务判别等许多任务。数据仓库层(DW)是数据仓库的主体。在这里,从ODS层获取的数据根据??主题建立各种数据模型。例如,可以将研究者旅游消费为主题的数据集与航空公司的登机和旅游信息、银联系统的刷卡记录进行组合分析,生成一个数据集。在这里,我们需要了解四个概念:维度、事实(Fact)、索引(Index)和粒度(Granularity)。数据产品层(APP),这一层是提供数据产品使用的结果数据。在这里,主要用于数据产品和数据分析。在线系统一般存放在es、mysql等系统中,也可能存在于Hive或Druid中,用于数据分析和数据挖掘。比如我们常说的报表数据,或者那种又大又宽的表格,一般都放在这里。技术实践的三层技术划分比较粗粒度,后面我们会具体细分。在此之前,先说说每一层的数据一般是怎么流动的。这里只是简单介绍几个常用的工具,主要关注开源行业的主流。数据源层->ODS层这其实是我们大数据技术发挥作用的一个主战场。我们的数据主要来自两大来源:业务库,这里经常使用sqoop来提取,比如我们每天定时提取。实时性方面,可以考虑使用canal监控mysql的binlog,实时访问。埋日志,在线系统会进入各种日志。这些日志一般以文件的形式保存。我们可以选择使用flume定时抽取,也可以使用sparkstreaming或storm实时访问。当然,Kafka也会是一个关键的角色。其他的数据来源会比较多样化,跟具体的业务有关,这里不再赘述。注意:这一层应该不是简单的数据访问,而是要考虑一定的数据清洗,比如异常字段的处理,字段命名的规范化,时间字段的统一等等,一般这些容易被忽略,但它们仍然很重要。尤其是后面我们做各种特征的自动生成的时候,会非常有用。以后会有文章分享。ODS、DW–>App层也主要分为两种:每日定时任务类型:比如我们典型的每日计算任务,每天早上计算前一天的数据,早上看报表。这类任务往往使用Hive、Spark或原始MR程序进行计算,并将最终结果写入Hive、Hbase、Mysql、Es或Redis。实时数据:这部分主要是各种实时系统用到的,比如我们的实时推荐,实时用户画像。一般我们会用SparkStreaming、Storm或者Flink去计算,最后落到Es、Hbase或者Redis。比如原来的设计分为6层,去掉metadata后还是5层。我们来分析一下最初的设计思路。缓冲层(buffer)概念:也称为接口层(stage),用于存储每天的增量数据和变化数据,比如Canal接收到的业务变化日志。数据生成方式:直接从kafka接收源数据,需要每天生成业务表。对于更新、删除、插入数据,只生成插入数据的业务表,数据直接进入明细层。讨论方案:只将运河原木直接放入缓冲层,其他有拉链数据的业务也放入缓冲层。日志存储方式:使用impalaappearance和parquet文件格式,方便读取需要MR处理的数据。日志删除方式:长期保存,只能保存最近几天的数据。讨论方案:直接长期存储。Tableschema:一般按天创建分区。库和表命名。库名:buffer,表名:初步考虑格式为:buffer_date_business表名,待定。明细层(ODS,OperationalDataStore,DWD:datawarehousedetail)概念:是数据仓库的明细数据层,沉淀STAGE层的数据,降低抽取的复杂度。同时,ODS/DWD的信息模型组织主要遵循企业业务交易处理的形式,集中了各种专业数据,明细层的粒度与阶段层的粒度一致,是一个公共的分析资源。数据生成方式:部分数据直接来自kafka,部分数据由接口层数据和历史数据合成。运河日志合成数据的方式有待研究。讨论方案:渠道数据合成方法如下:每天将前天的全量数据和明细层昨天的新数据合成一个新的数据表,覆盖旧表。同时使用历史镜像,每周/每月/每年存储一个历史镜像到新表中。日志存储方式:直接数据使用Impala外观,parquet文件格式,canal合成数据为二次生成数据,推荐使用内表,以下各层都是Impala生成的数据,推荐使用内表+static/动态分区。日志删除方式:长期保存。Tableschema:一般按天创建分区,分区字段根据具体业务选择,没有时间概念。库和表命名。数据库名:ods,表名:初步考虑格式为ods_date_business表名,待定。旧数据更新方式:直接覆盖。轻度汇总层(MID或DWB,datawarehousebasis)概念:轻度汇总层数据仓库中DWD层和DM层之间的一个过渡层,是对DWD生产数据的轻度综合和汇总统计层(可以进行复杂的清洗和处理,比如根据PV日志生成的session数据)。轻综合层和DWD的主要区别在于两者的应用领域不同。DWD的数据来自于生产系统,不满足一些不可预见的需求而沉淀下来;轻综合层是细粒度的,适合分析应用。统计和降水。数据生成方式:明细层根据一定的业务需求生成轻汇总表。需要复杂清洗的数据和需要在详细层进行MR处理的数据也进行处理,然后连接到轻度汇总层。日志存储方式:内表,parquet文件格式。日志删除方式:长期保存。Tableschema:一般按天创建分区,分区字段根据具体业务选择,没有时间概念。库和表命名。数据库名:dwb,表名:初步考虑格式为:dwb_date_business表名,待定。旧数据更新方式:直接覆盖。主题层(DM,数据市场或DWS,数据仓库服务)概念:也称为数据集市或宽表。根据业务的划分,如流量、订单、用户等,生成一个多字段的宽表,提供后续的业务查询、OLAP分析、数据分发等。数据生成方式:通过计算生成浅层摘要层和详细层数据。日志存储方式:使用impala内表,parquet文件格式。日志删除方式:长期保存。Tableschema:一般按天创建分区,分区字段根据具体业务选择,没有时间概念。库和表命名。数据库名:dm,表名:初步考虑格式为:dm_date_business表名,待定。旧数据更新方式:直接覆盖。应用层(App)概念:应用层是根据业务需要,对前三层数据进行统计得到的结果,可以直接提供查询展示,或者导入到Mysql中使用。数据生成方式:由明细层、简明层、数据集市层生成。一般要求数据主要来自于集市层。日志存储方式:使用impala内表,parquet文件格式。日志删除方式:长期保存。Tableschema:一般按天创建分区,分区字段根据具体业务选择,没有时间概念。库和表命名。库名:暂定apl,根据业务不限库。旧数据更新方式:直接覆盖。如何更优雅?上面的设计其实还是比较详细的,只是可能层数多了一点,在区分一张表应该放在哪里的时候可能会有点混乱。本章我们设计了另一套数据仓库层,同时在前面的基础上增加了维度表和一些临时表的注意事项,让我们的方案更加优雅。在下图中,做了一些小改动。我们去掉了上一节的Buffer层,将数据集市层和轻汇总层放在同一层,同时将维度表和临时表分开。这里解释一下DWS、DWD、DIM和TMP的作用。DWS:lightsummarylayer,从ODS层对用户行为做一个初步的总结,抽象出一些常用的维度:time,ip,id,并根据这些维度做一些统计值,比如每个时间段的用户不同登录ip购买的商品数量等。这里做一个简单的汇总,计算效率会更高。在此基础上计算只有7天、30天、90天的行为会快很多。我们希望80%的业务可以通过我们的DWS层来计算,而不是ODS。DWD:这一层主要解决一些数据质量问题和数据完整性问题。比如用户的个人资料信息来自很多不同的表,经常会出现延迟、数据丢失等问题。为了方便各个用户更好的使用数据,我们可以在这一层做一个屏蔽。DIM:这一层比较简单。举个例子来理解,比如国家代码和国名、地理位置、中文名字、国旗图片等信息都存储在DIM层。TMP:在每一层的计算中都会有很多临时表,专门设置了一个DWTMP层来存放我们数据仓库的临时表。总结数据分层是数据仓库中非常重要的一个部分。它不仅决定了一个层面的问题,还直接影响到血缘关系分析、特征自动生成、元数据管理等一系列后续建设。因此适合早期考虑。另外,大家也不必太在意每一层的名称,按照自己的喜好就好。本文分享了笔者自己对数据仓库的一些理解和思考,可能不是很准确。有问题可以多交流。初步估计在数据仓库方面,应该还有3个话题可以分享:血缘关系分析、特征自动生成、元数据管理。分享完成后,数据仓库相关工作就告一段落了。参考:1.《数据仓库》2.《数据仓库工具箱》3.Winston和Ruby的指导
