Dremel,Drill,OpenDremel 和Tenzing
最近mapr 向apache 提议了一个仿google dremel 的drill 项目
http://wiki.apache.org/incubator/DrillProposal?action=AttachFile&do=view&target=Drill+slides.pdf
里面提议做一个独立的执行引擎, 专门用来处理大数据量的,低延迟的数据分析任务.
第一个问题当然是为什么hive 不行:hive 是一个sql-mr 的解释器,又由于目前的hadoop 实现没有办法从本地起进程,所以延迟在大集群的环境下永远没有办法降下来. (大集群里网络和磁盘的优化比cpu 和内存的优化重要的多)
对比一下aster data , greenplum ,vertica 的类似的工具包,它们都是从本地起进程,读取每个节点上的数据库信息(文件位置和统计信息?)和文件格式.
最近看到的一个hadoop job 优化,也是写了一个c++ 的过滤引擎,在本地执行过滤,里面说提高了20倍的速度.
http://dev.datasift.com/blog/optimizing-hadoop-jobs
drill 的提议里面提到想支持多种数据源和数据格式,这个我个人到觉得比较有争议,如果性能对于这个项目非常重要,那么肯定有一种格式在多种条件下都能够表现更好,那么为什么不能提前转换格式呢?尤其是有必要支持文本格式嘛? drill 里面大概设想的列存储格式是由还没有实现的avro-806 来实现. 这个倒是我最关心的. (估计一个好的列文件格式都要做好多年)
重新又大致读了一遍dremel 的论文, 去年年初的时候看过一遍,里面介绍列数据库一些优化的部分我倒是没有鸭梨,但是里面那个Repetition Level 和Definition Level 等支持嵌套数据模型的东西完全把我搞糊了. 最近看了一些nosql 模型的文章,尤其是hbaseconf 上的hbase data model 的ppt ,觉得好像又比之前多领悟了那么一点点. 我个人的理解大概如下:
首先dremel 的模型并不是完全的动态,它跟hbase 可以在任意时刻可以添加任意列不一样,这个是由它前面的protocl buffer 的schema 定义的,里面是有明确定义repeated , enum 这种类型的,我目前仍然对repetition level 有一些疑惑的地方是: 如果不知道全部的唯一值,如何确定repetition level? 一种解释是在schema 定义的时候知道大概repetition level 不会超过一个比较小的值(比如1000),至少在dremel 举的这个例子里面是成立的,如果repeated 是一个原始数据类型(dremel 里面的例子就是backward, forward), 它存储的是一列,类型是list , 如果repeated 是一个group (dremel 例子里面就是Name 和Language) , 那么必须确保这个group 的个数是有限的,如果不是我就实在不知道它怎么确定repetition level 的了(它里面的顺序是固定的,固定字段没有值必须明确为null , 如果顺序不是固定的,并且个数不确定,根本就没有办法执行查询). 另外一种解释是dremel 是基于bigtable 的,这个在论文的Per tablet histograms 里面明确用的字眼是tablet , 所以是由tablet 来确定repeated group 的,同一个值在不同的tablet 里面是可以有不同的repetition level 的. 所以他的一个文件就是一个protocol buffer 的数据格式(里面叫ColumnIO), 多个protocol buffer 的格式可能是不同的.
dremel嵌套数据模型跟大多数nosql 的模型的出发点是一致的: 将物理储存相关的数据尽量放在一起,尽可能的提前做join 而不用去考虑数据冗余的问题,不用过多的去关注逻辑模型里面怎么切分和可能会怎么查询的问题.
dremel 论文中的用来测试的query 4 :
SELECT COUNT(c1 > c2) FROM
(SELECT SUM(a.b.c.d) WITHIN RECORD AS c1,
SUM(a.b.p.q.r) WITHIN RECORD AS c2
FROM T3)
他把两个不同层级的数据聚合在一个层级上进行比较,也是他充分利用了嵌套数据结构的特点,如果在关系数据库里,这个sql 类似于(实际上不对,要转成having ):
select count(c1) from t3 where c1 > (select c2 from t3 group by xxx where join_field = join_filed)
记得以前看过一个oracle 还是postgresql 查询计划优化的文章,里面提到这种不同层级的过滤要把他转换成类似
select count(c1) , (select count(c2) from t3 group by xxx where join_filed=join_filed ) c2
from t3 where c1 > c2
类似这种sql , 主要原因是selection 比 where 条件在数据库执行引擎里面会先执行,这样会过滤总体的数据量. 如果有些数据库不支持这种嵌套的子查询,可能就需要预处理成同一个层级的数据集了.
数据仓库建模所要求的技能实在是太综合性了,我个人认为其中至少需要的N个技能中要包括对底层所使用的数据库尤其是查询计划执行原理和优化有非常底层的了解,而且需要在线上生产环境中运行足够长时间,根据收集的性能信息做出不断调整,我本来打算写一篇数据仓库建模的文章的,也参考了很多这方面的文章,但是都觉得太理论了,谈论的还是N多年前的东西,三范式和星形模型,为什么选这个不选那个?在数据库什么场景下讨论?关键是都谈虚的,没有实际的例子来讲解,这让我想起了几年前跟一个同事讨论Teradata FDM 模型(teradata 针对银行的一个行业模型)的一个设计问题,好像是一个地方到底该使用一对多,多对多,还是多对一的问题争论了几天,最后没结果,其中一个原因可能是我们都没有做过银行的项目,也没有办法验证谁说得对,最后只能限于理论争论,这种不能验证的争论可能只会有害无益.(好吧,扯远了), 最近比较推荐的一个资料是dzone 的数据仓库refcard , dzone 有很多refcard 都很值得收藏的 , 这个refcard 至少让我搞懂了我一直没搞懂的缓慢变化维SCD type2,3 的查询应该怎么处理的问题, 强烈推荐一下:
http://refcardz.dzone.com/refcardz/data-warehousing
Dremel 和Tenzing 对比
tenzing 里面明确提到了在编译执行计划的时候翻译成dremel 的解释器还是很慢,并且dremel 是行式处理.也就是dremel 没有列的反序列化,列的执行引擎和ppd . 而Tenzing 里面提到的部分优化可以一定程度上弥补dremel 的这种不足.
dremel 的分区是基于bigtable 的,所以它是范围分区,每个分区的大小,个数,分布在多少机器上都是可以控制的,并且dremel 可以由bigtable 来提供它统计信息,tenzing 相对来说欠缺这一点. 在Tenzing 论文里面明确提到如果使用hash aggregation ,必须明确使用hint 而且如果内存使用过量会直接查询失败, 这证明在统计信息上面tenzing 的基于列的统计出现的偏差可能还是很大的.
tenzing 对于ppd , hash aggregation , 各种join 都有优化.
我原先读tenzing 论文的时候以为tenzing 是由dremel 发展而来的,但是看到了youtube 2011 data warehouse 的ppt ,又重新读了一遍,发现的确是两个不同的框架发展过来的,dremel 我猜测是bigtable 的核心,里面统计信息,延迟,和行的处理方式都感觉好像很多基于coprocess , coprocess 是google 09年推出的基于本地进程的rpc 框架,所以延迟即使在分析大数据量的时候也比较低,而tenzing 是在mr 上做类似列数据库的优化,tenzing 本身跟hive 一样是sql-mr 的解释器,他不是从本地起进程, 论文里面提到的一个优化是Local Exection 里面说如果数据量小于128M 就直接在本地执行. 另外里面说dremel 比tenzing 的延迟要明显小,可能一部分跟数据格式有关系吧,如果解决了数据加载的速度问题,我想统一的数据格式一定是必然的. (当然,主要原因永远是网络).
http://www-conf.slac.stanford.edu/xldb2011/talks/xldb2011_tue_1120_YoutubeDataWarehouse.pdf
这个ppt 在dremel 和tenzing 的文件格式上感觉也有一些端倪,dremel 的文件格式单一并且默认隐含只读,tenzing 支持多数据源,但是性能不好,那么换句话说,dremel 的加载速度明显不好? dremel 基于bigtable ,加载速度肯定是比基于mr 的差上1一个以上数量级的.
Google 的打算是把大部分Tenzing 的优化都迁移到dremel 上面去,
另外一篇opendremel 的作者也提到的dremel,tenzing 的对比:
http://bigdatacraft.com/archives/327
看到EMC 中国研究院的颜开同学也评论了一下opendremel,drill ,Tenzing,Dremel , 里面翻译了部分dremel 的论文, 颜开同学认为的opendremel 项目花了两年时间去做一个c++ 的虚拟化执行引擎和一个跟云储存集成的框架是越走越远,我个人到觉得工欲善其事必先利其器, c++ 的虚拟执行引擎是每一个大数据低延迟分析系统都必须要面对的,mpp 都是如此,google 做tenzing 的时候也研究了很多LLVM 的东西,google 的资源虚拟化一般都叫worker 也是业界都知道的. 而他们花时间做云储存跟OpenStack Swift 集成也是为了能够实现从本地执行进程做技术储备.
http://www.yankay.com/google-dremel-rationale/
http://code.google.com/p/dremel/
对于资源虚拟化的控制, 比如一个cpu core 和多大内存配对处理多大数据都是需要有估算的, 如果性能是非常重要的属性,这些基础的底层控制细节对于整体性能提升都是非常明显的. 比如在Jeff Dean 在2009 年的演讲里面提到的c++ 连新旧数据在磁盘的位置都会控制(第25页), 这个好像在oracle 11g 里面也有类似的特性:
不管是dremel,tenzing,drill,opendremel 还是其他的列数据库,大数据分析的战斗才刚刚开始,没个5年10年的研究和开发,都不能说自己满足了生产系统的要求,即使是google 的实现也只是尽量解决了简单的查询,同样可以看到需要努力的地方还有很多,包括反序列化,装载问题,执行器和优化器,各种join 的判断,延迟物化,分析能力的不足. 压缩. 高可用,多排序字段的判断,工作负载的控制,并行的粒度和自动化等等 , 如果读者对列数据库感兴趣,最近比较推荐的一篇vldb 的论文,当然还包括论文里面引用的多年来列数据库领域的多篇论文, 他里面执行计划那部分我最关心的写的好少,而且压缩那部分也没有他官网上写的12个压缩方法和适用场景来的详细,不过毕竟要介绍的太多了,一篇论文很难都说清楚
网站很不错哈~