最近主要在研究大数典型应用adhoc query,要实现秒级的adhoc query,通常有3种思路:
1、用搜索技术,将查询都建立索引,然后用搜索技术来实现。这种技术目前主要限制是索引建立和存储成本高,索引建立不及时,例如支付宝的higo。
2、实时计算,对不能指定维度的查询,理论上认为是实时计算,每个列上建立函数索引,这种典型的代表是mesa。关于mesa,前面我有篇简单的介绍性文章《mesa介绍:google 近实时数据仓库系统》,深入的大家可以看一看google的论文。淘宝的garuda公开的材料来看,主要也是实时计算的思路,但是目前garuda公开的资料不多,不知道目前这个系统到什么阶段了。
3、最后一种思路是利用MPP架构,通过并行扫描的技术来实现adhoc query。前面写了两篇分析文章《实时分析系统(HIVE/HBASE/IMPALA)浅析》和《 MPP DB 是 大数据实时分析系统 未来的选择吗?》。这两篇文章最新偶能发现被公司内部拿去作为参考,说明研究这块问题的人还不少,能拿我的文章去参考,应该还是比较认可我的思路的吧。O(∩_∩)O~
以上是业界目前我所知道的3种典型的思路,朋友们要是有新的思路欢迎多交流。
关于第3种思路,目前业界有很多引擎,各有优缺点,最近我萌发了另外一种考虑《一套数据,多种引擎(impala/Hive/kylin)》。前面说了这么久,关键还是要回到今天要讨论的正题上来,怎么做到一套数据?
数据分 metadata和 raw data。Impala一开始的思路就是用来改进hive的不足,所以和Hive天然共元数据,这里就不讨论元数据了。我们今天来简单对比分析一下业界典型的两种数据存储格式Parquet和ORCfile,分别是impala和Hive推荐使用的数据格式。
一、首先来看下ORCfile。
Orcfile(Optimized Row Columnar)是hive 0.11版里引入的新的存储格式,是对之前的RCFile存储格式的优化,是HortonWorks开源的。看下orcfile的存储格式:
可以看到每个Orc文件由1个或多个stripe组成,每个stripe250MB大小,这个Stripe实际相当于之前的rcfile里的RowGroup概念,不过大小由4MB->250MB,这样应该能提升顺序读的吞吐率。每个Stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer:
每个Stripe都包含index data、row data以及stripe footer,Stripe footer包含流位置的目录,Row data在表扫描的时候会用到。
Index data包含每列的最大和最小值以及每列所在的行。行索引里面提供了偏移量,它可以跳到正确的压缩块位置。
通过行索引,可以在stripe中快速读取的过程中可以跳过很多行,尽管这个stripe的大小很大。在默认情况下,最大可以跳过10000行。
因为可以通过过滤预测跳过很多行,因而可以在表的 secondary keys 进行排序,从而可以大幅减少执行时间。比如你的表的主分区是交易日期,那么你可以对次分区(state、zip code以及last name)进行排序。
每个文件有一个File Footer,这里面存的是每个Stripe的行数,每个Column的数据类型信息等;每个文件的尾部是一个PostScript,这里面记录了整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时,会seek到文件尾部读PostScript,从里面解析到File Footer长度,再读FileFooter,从里面解析到各个Stripe信息,再读各个Stripe,即从后往前读。
ORCFILE主要特点:
混合存储结构,先按行存储,一组行数据叫stripes,stripes内部按列式存储。
支持各种复杂的数据类型,比如: datetime, decimal, 以及一些复杂类型(struct, list, map, and union);
在文件中存储了一些轻量级的索引数据;
基于数据类型的块模式压缩:
a、integer类型的列用行程长度编码(run-length encoding)
b、String类型的列用字典编码(dictionary encoding);
二、再来看看Parquet
我们的开源项目 Parquet 是 Hadoop 上的一种支持列式存储文件格式,起初只是 Twitter 和 Coudera 在合作开发,发展到现在已经有包括 Criteo公司 在内的许多其他贡献者了. Parquet 用 Dremel 的论文中描述的方式,把嵌套结构存储成扁平格式。
尽管 Parquet 是一个面向列的文件格式,不要期望每列一个数据文件。Parquet 在同一个数据文件中保存一行中的所有数据,以确保在同一个节点上处理时一行的所有列都可用。Parquet 所做的是设置 HDFS 块大小和最大数据文件大小为 1GB,以确保 I/O 和网络传输请求适用于大批量数据(What Parquet does is to set an HDFS block size and a maximum data file size of 1GB, to ensure that I/O and network transfer requests apply to large batches of data)。
在成G的空间内,一组行的数据会重新排列,以便第一行所有的值被重组为一个连续的块,然后是第二行的所有值,依此类推。
为了在列式存储中可以表达嵌套结构,用叫做 definition level和repetition level两个值描述。分别表达某个值在整个嵌套格式中,最深嵌套层数,以及在同一个嵌套层级中第几个值。
Parquet 使用一些自动压缩技术,例如行程编码(run-length encoding,RLE) 和字典编码(dictionary encoding),基于实际数据值的分析。一当数据值被编码成紧凑的格式,使用压缩算法,编码的数据可能会被进一步压缩。Impala 创建的 Parquet 数据文件可以使用 Snappy, GZip, 或不进行压缩;Parquet 规格还支持 LZO 压缩,但是目前 Impala 不支持 LZO 压缩的 Parquet 文件。
除了应用到整个数据文件的 Snappy 或 GZip 压缩之外,RLE 和字段编码是 Impala 自动应用到 Parquet 数据值群体的压缩技术。
综合来看,ORCfiel和parquet本质上都是列上存储,大同小异。parquet主要特点是支持嵌套格式,ORCfile主要特点是strips中有轻量级的index data。所以这两种数据存储格式完全是可以相互借鉴融合的。
列示存储不是hadoop首创,是从传统数据库中发展而来。最后来看看wiki中介绍的列示存储的历史:
Column stores or transposed files have been implemented from the early days of DBMS development. TAXIR was the first application of a column-oriented database storage system with focus on information-retrieval in biology[11] in 1969. Statistics Canada implemented the RAPID system[12] in 1976 and used it for processing and retrieval of the Canadian Census of Population and Housing as well as several other statistical applications. RAPID was shared with other statistical organizations throughout the world and used widely in the 1980s. It continued to be used by Statistics Canada until the 1990s.
KDB was the first commercially available column-oriented database developed in 1993 followed in 1995 by Sybase IQ. However, that has changed rapidly since about 2004 with many open source and commercial implementations. MonetDB was released under an open-source license on September 30, 2004,[13] followed closely by the now defunct C-Store.[14] Vertica was eventually developed out of C-Store, while the MonetDB-related X100 project evolved into VectorWise.[15][16]