1、星型模型、雪花模型
1:星型模型、雪花模型的优缺点?
查询性能:雪花模型维度表、事实表之间的联接很多,性能比较低;星型模型数据冗余存储所以很多统计查询不需要做外部的连接。 模型复杂度:星型架构更简单。雪花模型数据模型的业务层级是由一个不同维度表主键-外键的关系来代表的。而在星形模型中,所有必要的维度表在事实表中都只拥有外键。 层次概念:雪花型架构更加贴近OLTP系统的结构,比较符合业务逻辑,层次比较清晰。 存储空间:雪花模型使用的是规范化数据,不会产生冗余数据,能够减少数据量,而相比之下星型架构会产生数据冗余。 ETL处理:雪花模型由于附属模型的限制,ETL相对复杂,不能并行化。星形模型加载维度表,不需要再维度之间添加附属模型,因此ETL就相对简单,而且可以实现高度的并行化。 适用场景:雪花模型更加适合维度分析的场景,星型模型更加适合指标分析的场景。
雪花模型适用场景:
根据我们的项目经验,一般建议使用星型架构。因为我们在实际项目中,往往最关注的是查询性能问题,至于磁盘空间一般都不是问题。当然,在维度表数据量极大,需要节省存储空间的情况下,或者是业务逻辑比较复杂、必须要体现清晰的层次概念情况下,可以使用雪花型维度。
1、一个用户维度表且数据量较大。其中,80%的事实度量表是匿名访问者,仅包含少数详细信息。20%的是可靠的注册用户,且这些注册用户有较为详细的信息,与多个维度表中的数据相连。
2、例如一个金融产品维度表,且这些金融产品有银行类的,保险类等等区别。因此不同种类的产品有自己一系列的特殊属性,且这些属性并非是所有产品共享的。
3、多个企业共用的日历维度表。但每个企业的财政周期不同,节假日不同等等。在数据仓库的环境中用雪花模型,降低储存的空间,到了具体某个主题的数据集市再用星型模型。
雪花模型使得维度分析更加容易,比如“针对特定的广告主,有哪些客户或者公司是在线的?”,星形模型用来做指标分析更适合,比如“给定的一个客户他们的收入是多少?”
2、维度退化
维度退化
特点:
1.没有对应的维度表的维度。
2.存储在事实表中
不可能将所有与业务相关的维度分类到一个紧凑的表集合中。类似这样的情况,将一个或者多个维度存储到事实表中是合适的选择。采用这种方法,存储事实表中的维度列被称为退化维度,退化维度的过程称为维度退化。这种退化维度一般都是事务的编号,如订单编号、发票编号等。这类编号需要保存到事实表中,但是不需要对应的维度表,所以称为退化维度。
规范化定义:当一个维度没有数据仓库需要的任何数据的时候就可以退化此维度,需要把退化的相关数据迁移到事实表中,然后删除退化的维度。与其他存储在维表中的维度一样 ,退化维度也可以用来进行事实表的过滤查询、实现聚合操作等。
退化维度常见于事务和累积快照事实表中。
退化维度通常被保留作为操作型事务的标识符。实际上可以将订单号作为一个属性加入到事实表中。这样订单维度就没有数据仓库需要的任何数据, 此时就可以退化订单维度。需要把退化维度的相关数据迁移到事实表中, 然后删除退化的维度。
核心理解:退化维度没有对应对应的维表,没有修饰它的属性,但是呢,通过它你可以获取一些内容,一些事实,比如说订单编号,你可以通过它获得这个订单里面包含哪些商品,对应的付款人是谁等。注意,对于不变维度,可以进行退化,对于缓慢变化维度,视具体情况而定,如果忽略缓慢变化维度的影响可以退化,否则不建议退化。
优点:
维度退化在事实表中有利于使用,一般一个维度键都有对应的维表,如果退化在事实表中,可以减少关联次数,并且退化维可以用于group by操作,进行分组统计。
弊端:
灵活度下降、耦合增多、冗余存储
缓慢变化维
一些维度表的数据不是静态的,而是会随着时间而缓慢地变化(这里的缓慢是相对事实表而言,事实表数据变化的速度比维度表快)。这种随着时间发生变化的维度称之为缓慢变化维。把处理维度表数据历史变化的问题,称为缓慢变化维问题,简称SCD问题
常见处理方案:
1.原样保留
对于某些维度属性,值不会发生变化,因此可以保留初始值,此方法什么也不做。例如日期维度的大多数属性,值都不会发生变化,如月份、季度、是否节假日等属性。
2.重写
该类型和业务系统保持一致,直接update,将维度属性修改为最新值,直接覆盖原有的值,不保留历史信息。该类型总是反映最近的情况,会破坏历史情况,因此适合业务只关心最新属性值、不关心历史信息的情况。
3.增加新行
在维度表中增加新的一行,新行中采用新的属性值。此方式及其变种是处理缓慢变化维的主要技术。
4.增加新列
该方法在维度表中增加新的一列以保存原来的属性值。
5.增加微型维度
当某维表是一个大型维度表,采用方式3时,如果某些维度属性变化相对较快,这将导致维度表中的数据量增长过快,带来过多的数据冗余存储,该维表变得越来越大,导致存储压力和性能压力,严重影响对历史数据的查询、分析效率。
6.快照维度
此种方式比较暴力,每天保留全量维度属性的快照数据,自然键及日期键作为事实表的外键。此方式依托的是当前存储成本远低于计算成本,以空间换时间的理念。
7.拉链表是方式3的变形,对于有变化频率不太高的维度属性,相较于方式6,大大降低了存储;对于变化频率很高的维度属性,不适用此方法,可考虑垂直拆分。
总结:
不止上面7种,还有三种组合方式(微型维度与方式2支架、方式2属性增加到方式3维度、双重外键并且方式2与方式3的结合)不常用。
方式2适合不关心历史信息的业务场景;
方式3最为常用,但不适合处理变化十分迅速的维度属性;
方式4不太常用,适合维度变化次数很少(如不超过两次)的场景;
在大数据时代,方式6、7比较常见。
方式6简单粗暴、易于理解和使用,但是存储成本高,造成了很大的存储空间的浪费;
方式7相对存储空间小,但是使用成本高,对于BI及其他下游使用人员来讲,不易于理解,另外该方法可以很方便的找到某一时间有效的数据(生效日期<= 选择的时间<=失效日期),但是对于某一段时间生效的数据则不太好关联,需要做技术改造。
Hash shuffle与Sort shuffle的区别?
Hash shuffle:一种是普通运行机制,另一种是合并的运行机制。
产生的磁盘小文件的个数为maptask*reducetask
每个分区是一个task
磁盘小文件多,I/O增多,产生的GC会增多。
这种shuffle产生的磁盘小文件,容易导致OOM
这种模式不单单产生的磁盘小文件比较多,而且占用内存也比较多。
我们应该降低这种磁盘之间的接触。
Hash shuffle的优化机制
启动HashShuffle的合并机制ConsolidatedShuffle的配置:spark.shuffle.consolidateFiles=true
两个task共用一个buffer缓冲区
如果 Reducer 端的并行任务或者是数据分片过多的话则 Core * Reducer Task 依旧过大,也会产生很多小文件。
sort shuffle:
Spark1.6之前用hash shuffle,在spark1.6之后使用sort shuffle
Sort shuffle的两种机制:
估算,去要内存5.01*2-5
要不到的时候就去排序
最终溢写的小的磁盘小文件合并成为了一个大的磁盘小文件
当不需要排序的时候,默认使用Bypass机制
bypass运行机制的触发条件:
Shuffle reduce task 数量小于spark.shuffle .sort.bypassMerge Threadshold参数的值小于200,不开启,溢写磁盘不需要排序,小于等于的时候是开启的。
不是聚合类的shuffle算子(比如reduceByKey)。
hash shuffle(合并运行机制)优化机制产生的磁盘小文件的个数:C*R(core*reducer)
Hash shuffle(普通):产生的磁盘小文件:M*R
Sort shuffle产生的磁盘小文件的个数为:2*M
Bypass机制产生的磁盘小文件的个数为:2*M
spark容错重试机制
重试机制
1、Application级别的容错 spark.yarn.maxAppAttempts
如果没有手动配置这个参数,那就会使用集群的默认值yarn.resourcemanager.am.max-attempts,默认是2,这是hadoop的yarn-site.xml里面配置的,当然spark.yarn.maxAppAttempts要小于yarn.resourcemanager.am.max-attempts值,才生效。
2、executor级别的容错 spark.yarn.max.executor.failures
参数:spark.yarn.max.executor.failures= max( numExecutors * 2 , 3)
说明:如果 executor failed 一定数量后,整个 Spark 任务就会kill 掉。
3、stage级别的容错 spark.stage.maxConsecutiveAttempts
参数:spark.stage.maxConsecutiveAttempts=默认为 4
说明:在一个 stage 被中止之前,允许的连续 stage 重试的次数
4、task级别的容错 spark.task.maxFailures
参数:spark.task.maxFailures= 默认为 4次,允许重试次数=此值-1。
说明:Task 重启次数超过 spark.task.maxFailures,则 taskSet 会失败,即一个 stage 失败。stage 失败导致整个 Job 就失败了,spark 会取消该 stage 对应的 job 包含的所有 task,并返回用户任务执行失败。
在大作业(处理的数据量比较大)的情况下,建议可以设置为8次
额外增加程序鲁棒性的机制
5、shuffle的io级别的容错 spark.shuffle.io.maxRetries
默认参数是3次。shuffle拉取数据的时候,有可能连接的那台机器正在gc,响应不了,所以拉取shuffle-io有重试,还可以设置重试的间隔等等,这里就不列出来了
6、rpc级别的重试
spark中,相互通信,基本上都是rpc发送,举个例子,一个task处理完了,通过spark内置的RPC框架往endpoint发送处理完了的消息,RPC的服务端,拿到这个消息做一个后续的处理,这之间的通信也需要有重试等机制,如果处理的数据量比较大,应该适当增加上述参数的时间
7、推测执行
其实我一直不太爱用推测执行,原因是这样的,当某个task执行很慢的时候,排除机器的问题,那基本上是数据倾斜,既然是数据倾斜,那我再启动另一个task来跑,同样是很慢,没什么太大区别,所以推测执行的适用场景,应该是:
1、部分机器性能不行,相同数据量的task分发到这些机器上运行会比其他机器慢很多
2、由于数据本地化策略,把大部分任务扔到了相同的几台机器上运行,其他机器围观
3、部分task由于一些奇怪的原因卡住了
类似以上的情况,可以尝试开启推测执行来解决问题,但是推测执行势必会影响spark任务的运行速度
8、黑名单机制
黑名单机制的配置参数越来越多,证明spark是有在这上面花功夫的。本质上来讲,其实就是大数据集群的部分机器可能因为某些原因(比如坏盘,cpu/io爆满),导致分发到该机器上的task并不能完成,但是由于数据本地化策略,有可能task失败重试的时候又分发到这台机器上,这就很不合理。所以可以设置,当一个task在某台机器上失败多少次,该台机器就会被加入黑名单
其他相关参数请看spark官网,因为不同版本配置不一样!
http://spark.apache.org/docs/latest/configuration.html
我没有截全,还是不少的
9、cache机制
cache机制算是代码和数据层面的容错机制
cache机制会保留数据在内存或者磁盘上,并且保留RDD的上下游依赖关系
他的大致的原理是这样的,数据流入spark,会根据用户写的代码构建DAG图,会生成不同的RDD,并且他们之间有上下游的依赖关系。
10、checkpoint机制
checkpoint有点像快照,像spark和flink这种提供流式的数据处理框架,基本上都会提供这种机制。
checkpoint机制,像是cache的一个递进的解决方案,当我们cache数据的时候,数据可能会存在内存中或者某部分机器的磁盘上,如果这些机器挂掉了,那cache失效,结果还是要从最原始的地方拉取数据!
checkpoint机制可以帮助你,把数据的结果写入分布式存储系统里,比如HDFS,通过HDFS来保证数据的不丢失,这样就算spark任务挂掉了,下次启动spark任务的时候还能够重新读到上一次checkpoint的数据,这个机制,一般用于流式的数据处理,记录偏移量等操作