数据仓库: 数据仓库是一个面向主题的、集成的、非易失的、随时间变化的数据集合。重要用于组织积累的历史数据,并且使用分析方法(OLAP、数据分析)进行分析整理,进而辅助决策,为管理者、企业系统提供数据支持,构建商业智能。
面向主题:为数据分析提供服务,根据主题将原始数据集合在一起。
集成的:原始数据来源于不同的数据源,要整合成最终数据,需要经过 ETL(抽取、清洗、转换)的过程。
非易失:保存的数据是一系列历史快照,不允许被修改,只允许通过工具进行查询、分析。
时变性:数仓会定期接收、集成新的数据,从而反映出数据的最新变化。
数据仓库 VS 数据库
数据库面向事务设计,属于OLTP(在线事务处理)系统,主要操作是随机读写,在设计时尽量避免冗余,采用符合范式规则来设计。
数据仓库是面向主题设计的,属于 OLAP(在线分析处理)系统,主要操作是批量读写,关注数据整合,以及分析、处理性能;会有意引入冗余,采用反范式方式设计。
| 数据库 | 数据仓库 | |
|---|---|---|
| 面向 | 事务 | 分析 |
| 数据类型 | 细节、业务 | 综合、清洗过的数据 |
| 数据特点 | 当前的、最新的 | 历史的、跨时间维护 |
| 目的 | 日常操作 | 长期信息需求、决策支持 |
| 设计模式 | 基于 ER 模型,面向应用 | 星形 / 雪花模型,面向主题 |
| 操作 | 读 / 写 | 大多为读 |
| 数据规模 | GB ~ TB | >= TB |
数仓分层:

数据应用层(ADS,Application Data Store)
数据主题层(DWT,Data Warehouse Topic)
数据汇总层(DWS,Data Warehouse Summary)
明细数据层(DWD,Data Warehouse Detail)
原始数据层(ODS,Operation Data Store)
数仓为什么分层
隔离原始数据:不论是数据异常还是数据的敏感性,使真实数据与统计数据解耦开
把复杂问题简单化:将复杂任务分解多层,每层处理简单的任务,方便定位各位问题
减少重复开发:规范数据分层,通过中间层数据,能够减少大量重复计算,增加一次计算结果的复用性
ETL 流程:
ETL – Extract - Transform - Load
构建数据仓库的重要一环,用户从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中去。
数据抽取
抽取方式
数据转换
数据加载
ETL 策略
全量同步:
增量同步:
如果担心数据更新出错,可以采用分区方式,每天保存最新的全量版本,保留较短周期。
操作数据层(ODS)

数据明细层(DWD)
数据汇总层(DWS)
数据应用层(ADS)
OLTP(在线事务处理)系统中,主要操作是随机读写,为了保证数据一致性、减少冗余、常使用关系模型,满足第三范式。
OLAP(在线联机分析)系统中,主要操作是复杂的分析查询;关注数据整合,以及分析、处理性能。
OLAP 按照数据存储方式的不同,可分为 ROLAP、MOLAP、HOLAP。
ROLAP(关系型 OLAP,Relation OLAP):使用关系模型构建,存储系统一般为 RDBMS
MOLAP(多维性 OLAP,Multidimensional OLAP):预先聚合计算,使用多维数组的形式保存数据结果,加快查询分析时间
HOLAP(混合架构的 OLAP,Hybrid OLAP):两者的集成,如底层是关系模型,高层是多为矩阵型;查询效率高于 ROLAP,低于 MOLAP
ROLAP:ER 模型、维度模型、Data Value、Anchor
维度模型的分类
星型模型:维度只有一层,分析性能最优
雪花模型:具有多层维度,比较接近 3NF,较为灵活
星座模型:基于多个事实表,事实表之间会共享一些维度表
模型选择:优先考虑星型模型
维度模型表的分类
事实表:
维度表:
事务事实表:
周期快照事实表:
不会保留所有数据,只保留固定时间间隔的数据。
随着业务周期的推进而变化,可完成间隔周期内的度量统计,比如年、季度累计。
使用周期+状态度量的组合,如年累计订单数(年是周期、订单总户数是度量)。
累计快照事实表:
用于跟踪业务事实的变化。
记录不确定周期的度量统计,完全覆盖一个事实的生命周期,如订单状态。
通常具有多个时间字段,用于记录生命周期中关键的时间点(如下单时间、支付时间、确认收货时间)。
实现方式一
使用日期分期表,全量数据记录,每天的分区存储昨天全量数据与当天的增量数据合并的结果
数据量大会导致全量表膨胀,存储大量永远不更新的冷数据,降低性能
使用于数据量少的情况
实现方式二
使用日期分期表,推测数据最长生命周期,存储周期内数据;周期外的冷数据存储到归档表
需要保留多天的分区数据,存储消耗依然很大
实现方式三
使用日期分区表,以业务实体的结束时间分区,每天的分区存放当天结束的数据;设计一个时间非常大的分区,如 9999-12-31,存放截至当前未结束的数据
已结束的数据存放到相应的分区,存放未结束数据分区,数据量不会太大,ETL 性能好
无存储浪费,数据全局唯一
业务系统可能无法标识业务实体的结束时间,可以使用其他相关业务系统的结束标志作为此业务系统的结束,也可以使用最长生命周期时间或者前端系统的数据归档时间
拉链表:
宽表模型是维度模型的衍生,适合 join 性能不佳的数仓产品。宽表模型是将维度冗余到事实表中,形成宽表,依次减少 join 操作。
宽表出现在DWD层、DWS层,由于宽表是将不同的内容组合到一张表中,所以宽表不满足范式要求,但是再增加冗余的同时提高了查新的性能(减少 join)。
MOLAP 将数据进行预结算,并将数据结构存储到 CUBE 模型中。MOLAP 产品:Kylin、Druid
CUBE 模型以多维数组的形式,物化到存储系统中,加快后续的查询。生成 CUBE 需要大量的时间、空间,维度预处理可能会导致数据膨胀。
MOLAP 对复杂查询操作做了直观的定义,包括钻取、切片、切块、旋转。

钻取:
钻取是对不同层次的分析,通过改变维度的层次来变化分析的粒度。
钻取包括上卷(Roll-up)、下钻(Drill-down)。

切片(Slice):
选择某个维度进行分隔称为切片

切块(Dice):
按照多维进行的切片称为切块
旋转(Pivot):
对维度方向的互换,类似于交换坐标轴上卷。
[外链图片转存中…(img-uQis5F2c-1645262440294)]
范式
第一范式:属性不可分割
第二范式:消除不分函数依赖
第三范式:消除传递依赖
关系建模与维度建模
关系建模:将复杂的数据抽象为两个概念——实体和关系,并使用规范化的方式表示出来。
维度建模:模型相对清晰、简洁。维度模型以数据分析作为出发点,不遵循三范式,故数据存在一定的冗余。维度模型面向业务,将业务用事实表和维度表呈现出来。
ODS:
DWD:
DWD层需构建维度模型,一般采用星型模型,呈现的状态一般为星座模型。
维度建模一般按照以下四个步骤:选择业务过程→声明粒度→确认维度→确认事实。
DWD层是以业务过程为驱动。
DWS层、ADS层都是以需求为驱动,和维度建模已经没有关系了。
DWS层建宽表,按照主题去建表。主题相当于观察问题的角度,对应着维度表。
DWS:
DWS称宽表层,这两层的设计思想大致相同,通过以下案例进行阐述。
问题引出:两个需求,统计每个省份订单的个数、统计每个省份订单的总金额
处理办法:都是将省份表和订单表进行join,group by省份,然后计算。同样数据被计算了两次,实际上类似的场景还会更多。
那怎么设计能避免重复计算呢?
针对上述场景,可以设计一张地区宽表,其主键为地区ID,字段包含为:下单次数、下单金额、支付次数、支付金额等。上述所有指标都统一进行计算,并将结果保存在该宽表中,这样就能有效避免数据的重复计算。
ADS:
如对电商系统各大主题指标分别进行分析。
事实表同步策略:
事务型事实表:适用于数据写入后不会发生变化的业务,增量同步;
周期型快照事实表:只关心每天、每周(时间间隔)的结果,每个周期全量同步
累积性全量事实表:适用于会发生周期性变化的业务,数据多累计写入(修改),新增及变化同步
DWD层构建维度模型策略:
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我希望将Favorite模型添加到我的User和Link模型。业务逻辑用户可以有多个链接(即可以添加多个链接)用户可以收藏多个链接(他们自己的或其他用户的)一个链接可以被多个用户收藏,但只有一个所有者我对如何为这种关联建模以及在模型就位后如何创建用户收藏夹感到困惑?classUser 最佳答案 下面的数据模型怎么样:classUser:destroyhas_many:favorite_links,:through=>:favorites,:source=>:linkendclassLink:destroyhas_many:favor
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2