impala paper笔记

不生产博客,只是汉化别人的成果

目录

摘要

介绍

用户角度的impala

物理schema设计

sql 支持

架构

state distribution

catalog service

FRONTEND

BACKEND

runtime code generation

I/O管理

Storage Formats

评估

ROADMAP


impala paper的链接

http://cidrdb.org/cidr2015/Papers/CIDR15_Paper28.pdf

摘要

impala是一个现代化,开源的mpp sql引擎架构,一开始就是为了处理hadoop环境上的数据。impala提供低延迟和高并发的query对于hadoop上的BI/OLAP,不像hive那样的批处理框架,这篇paper从使用者的角度阐述impala的总体架构和组件,简要说明Impala较别的sql on hadoop的优势

介绍

impala是开源的,最先进的mpp sql引擎,与hdaoop高度集成,高伸缩、高灵活。impala的目的是结合sql支持与传统数据库的多用户高性能(高并发)在hadoop上

不像别的系统,eg:postgre,impala是一个全新的引擎,由c++和java编写,拥有像hadoop一样的灵活性通过结合一些组件,eg:hdfs、hbase、hive metastore等等,并且能够读取常用的存储格式数据,eg:parquet、rcfile、avro等,为了降低延迟,没有使用类似mapreduce和远程拉取数据,impala实现了一个分布式的架构基于daemon进程,该进程负责接受所有的查询请求并且运行在hadoop上面,这样做的结果导致性能依赖于负载(就是并发高了查询就慢)

后面主要吹impala有多牛b,尤其在多用户环境下,吊打所有sql-on-hadoop

用户角度的impala

impala是一个集成hadoop的query引擎,可以结合一些组件比如metastore、hdfs、hbase来提供一个类rdbms的使用体验

impala专门用来与商业BI智能集成,所以客户端可以使用标准的jdbc、odbc来访问,认证通过kerberos或者ldap,授权也是标准的sql role和权限(类似sentry,role是权限的集合),为了查询hdfs的数据,用户创建表通过类似create table的语法,提供对数据的逻辑schema,也是物理的layout,例如,hdfs的文件和目录

物理schema设计

创表的时候,用户可以指定分区

create table t (...) partitioned by (day int) location 'hdfs路径' stored as parquet

对于未分区的表,数据都存在表的目录下,对于分区的表,数据存放在表目录的子目录下,类似hive。例如对于表zlq,分区day=17的数据都放在zlq/17/下,注意,这种分区下的数据只是在hdfs的一个目录下,但block还是按128M分布在不同节点间

impala也给用户高灵活性对于选择文件格式,支持textfile的压缩与不压缩,sequence file,rcfile,avro,parquet。不仅可以对表指定一种格式,也可以对各个分区指定不同的格式


sql 支持

impala支持大部分的sql-92语法,还有部分的sql-2003 分析函数,和大多数的标准字段类型,比如整型、浮点、string,char,varchar,timestamp,decimal,也可以实现udf通过java或者c++,和udaf通过c++,当前不支持java,不知道现在支持不

由于hdfs本身的限制,impala不像传统的RDBMS,它不支持update、delete(除了kudu),仅仅支持insert into .. select..,

用户可以通过hdfs的copy或mv数据文件到表的数据目录,也可以使用load data来加载数据

类似bulk insert,可以删除表的数据通过alter table drop partition,因为它不可能去更新hdfs的文件数据,impala不支持updata,但是可以insert overwrite某个分区

当数据load完,只要涉及到数据的change,无论什么时候,都需要compute stats <table>,将表的统计信息给到Impala优化器,以便后续查询选择最优方式

每次执行compute stats table就是给所有字段干了下面这个事,ndv类似distinct,只是不是准确值,预估,所有表越大,字段越多,compute stats时间越长

select count(*) from table

架构

impala是一个massively-parallel引擎,运行在成百上千台hadoop上,与底层存储引擎完全隔离,不像传统的RDBMS,紧密的结合在一起

impala部署需要3个角色,impalad服务负责接受客户端请求并且分发查询段在集群间,并且执行单个查询段。jdbc连的impala节点会充当查询的coordinator角色,所有的impalad服务都是平等的,这样也提供了负载均衡和容错的可能

一个impalad角色部署在有datanode的节点上,这样有利于impala从本地读取数据,不需要通过网络拉取底层数据,

statestore角色是impala的元数据的发布订阅服务,广播变化的元数据到所有的impalad节点,部署在单节点上就可以

catalog角色作为元数据访问的gateway,通过catalog,impalad可能执行ddl操作将元数据分发到外部存储例如hive metastore

这些impala的服务都是有配置选项的,比如资源池大小,可用内存等等

state distribution

状态分发,用词狂魔呀,statestore就负责分发、广播元数据

对于mpp数据库一个大的设计挑战就是怎么在那么多机器上同步元数据,impala是symmetric-node架构(各个impalad之间是平等的),要求所有计算节点都能够接收query请求并且执行查询,所以,所有的计算节点必须有最新版本的元数据和知道集群中哪些计算节点还活着,以便正确调度,避免出现把查询段分给一个已经宕掉的节点

当然可以设计成一个单独的管理节点,有整个集群的元数据,那个计算节点接收到查询请求,就去该节点拉数据,这样虽然可以保证每次的数据都是最新的,但是impala设计的时候尽量避免关键的步骤使用同步的rpc,觉得可能这样的话,在高并发场景下,每个计算节点都去请求元数据,势必会有性能瓶颈,就是查询的延迟都用来干网络连接、拉取远程信息。所以,impala设计了一个基于MQ的服务,statestore来广播元数据的改变

这个statestore包含一组topic,<key,value,version>,称它为entries,kv为二进制数组,version为64位整型,topic是别的服务定义的,statestore不负责管理里面存的什么玩意,topic的生命周期很长,但服务启停时不会持久化这些东西,订阅者期望接收到任意topic更新的信息,只要在statestore启动的时候注册、并且提供下topic即可。statestore响应这些订阅者通过发送第一次topic数据,包含当前topic所有信息,类似消费者吧,只要告诉statestore你需要那个topic,它就会不断的发变化给消费者

注册以后,statestore定期发两类信息给每个消费者,一类是topic的数据更新、删除、新增等,每个消费者包含每个topic的版本表示,所以statestore只要发送修改的信息即可,第二类是impalad的keepalive,就是那个计算节点还有心跳,超时的话将重新注册到statestore。之前版本的statestore都是使用topic来实现这两消息的传递,但是随着数据量增大,分发消息到每个消费者变得异常困难,尤其是故障检测中的误报,如果检测到失败的消费者(比如keepalive重试多次仍然失败),将不再发送更新的元数据信息,一些topic里的entries可能被标记为'transient',就是那个节点宕了。(一脸懵逼,不知道想表达啥,可能翻译的有问题)

statestore提供非常弱的语义,消费者可能接收更新以不同的速率(尽管statestore尝试公平分发),所以对于一个topic的内容可能有不同的view。然而,impala仅仅使用本地的元数据来做决策,不会去读集群内别的元数据,比如,一个计算节点接到query请求,直接解析分发到别的节点,不要求别的执行节点有相同版本的元数据和解析的节点。

虽然部署的时候只有一个statestore,发现中等规模的集群下,表现还可以,(擦,也就是大了,这还是有瓶颈),statestore不持久化元数据,只是push给活着的消费者。所以statestore被重启,计算节点会到这重新注册,所以不需要高可用,宕了,在别的节点重新起就可以了

catalog service

该服务主要服务与计算节点通过statestore的广播机制,执行ddl操作。这个服务pull信息从第三方的元数据存储(eg:hive的metastore或者hdfs的namenode),并且聚合成与Impala兼容的catalog structure,这种架构允许impala不必知道它底层的存储引擎,直接添加到元数据即可。任何对catalog系统的该表将通过statestore广播出去,该服务也允许我们扩展catalog 系统,比如只注册udf到该服务,没有持久化到hive metastore

由于catalog通常会非常大,访问这些表一般不会一下访问所有,该服务启动的时候仅仅加载一些比较粗粒度的信息,更多的详情还需访问第三方存储,如果刚启动时有对某张表的请求,该服务会优先加载该表的全部信息

 

当执行ddl的时候,如果使用的是Impala,那么元数据会到catalog,并持久化到hive metastore,然后当后面有query用到这张表时,会先执行invalidate metadata db.table,默认第一次用到该表的时候会拉取元数据,也可以改为创完以后就拉取,有个参数可以设置,当官网建议用到再取,一来好多表不会用户,就没必要拉元数据到每个节点,二来impala重启的时候,会加载大量无用的元数据

下面这个参数就是控制什么时候加载元数据

-load_catalog_in_background

FRONTEND

impala的”前端“ 负责将sql编译成可执行的查询计划供后端执行,是通过java写的,由功能完备的sql解析器和基于成本的优化器组成,所有的实现来自scratch(山寨的scratch?),除了支持基本的sql语法,还支持inline view(内联视图?什么鬼),uncorrelated and correlated subqueries(不相关和相关的子查询),多种join和窗口函数

查询编译过程类似传统的步骤,query解析,语义分析,查询计划/优化,impala着重与后者,impala的查询计划器以一棵解析树和语义分析过程中组合的信息(表、字段标识等等)作为输入,一个执行计划的生成分为两个阶段,单节点的计划、计划并行化和查询段

在第一阶段,解析树被转化成一个不可执行的单节点计划树,由以下一系列节点组成:scan,hash-join,cross join,union,hash aggregation,sort和top n等,这一步主要负责分发predicates(谓词)根据where条件、修剪分区、设置limit/offset,使用列投影(不知道是个啥),和基于成本来优化计划像窗口聚合分析,join重排序,成本估算是基于表/分区的基数(数据量?)+字段去重后数据量(不是count distinct,使用ndv预估),histograms(直方图?)当前不是统计信息的一部分,下面那句不知道啥意思,等以后再改

 Impala uses simple heuristics to avoid exhaustively enumerating and
costing the entire join-order space in common cases.

第二个阶段,将单节点的执行计划转化为一个分布式的可执行计划,目标就是最小化数据移动和最大化scna locality(局部性,可以想成本地性吧,不通过网络拉取数据),在hdfs上,远程拉取比local读会慢很多,这个计划将是分布式的,根据需要添加exchange节点(比如需要shuffle的时候),添加非-exchange节点来最小化数据移动,在第二阶段期间,我们选择join方式对于每个join(这时候join顺序已经是固定了,第一个阶段已经干了这事了),支持的join方式有broadcast and partitioned,前者将整份数据广播到每个节点,后者以关联字段re-hash,impala选择join方式基于最小化网络fetch数据量。

所有的要执行的聚合都会做一个本地pre-聚合(牛逼呀,spark就需要了解哪些rdd api会本地聚合,哪些不会),对于group 聚合,预聚合的输出将会partitioned好根据groupby条件(类似spark shuffle write,都是partitioned-然后网络fetch属于自己的),merge-聚合将会在所有节点并行完成。对于不是group 的聚合,这个merge-聚合在一个节点执行,(类似count(distinct )都会拉到一个节点上执行),sort和top n也是用类似的方法做的,分布式sort/topn完再执行单点merge操作。分析函数(窗口函数)也是并行的基于partition-by表示式,它的输入已经partitioned或者已经sorted,最后这个分布式计划树在exchange节点处被split,(类似spark划分stage,在shuffle处切)。每个计划的一部分都是一个查询段,它是后端impala执行的最小单位

上面这幅图就是说明一个单节点执行树怎么转换成分布式的,t1、t2是hdfs,t3是hbase(貌似也是hdfs),3表关联聚合排序取topN,可以看到t1、t2通过partitioned join关联,以关联字段re-hash,t3是被广播出去的,然后每个节点预聚合,继续以group by字段re-hash,然后并行merge-agg, 然后每个再并行top-n,把结果拉取coordinator,算出最终topn返回给客户端

BACKEND

impala后端接收来自前端的查询段并且分分钟执行完,后端是c++写的,并且使用code generation at runtime(运行时代码生成优化技术?),所以有比起java更省资源

impala使用了数10年来对并行数据库的研究,执行模式是传统的Volcano-style和exchange操作,反正牛b就完事了,也看不懂后面写的啥,虽然很吃内存,但也是可以会使用磁盘的,只有下面几种会溢写磁盘,hash join,基于hash的聚合(聚合加group)和窗口函数

impala使用分区来完成join和聚合,下面这段话还不太理解,有的字段用来决定目标分区(join字段or group 字段)

That is, some bits of the hash
value of each tuple determine the target partition and the
remaining bits for the hash table probe

剩下的字段用来hash table的什么东西?正常操作的话,如果hash table能够完全放在内存,分区开销很小,有内存压力则会被溢写磁盘,当构建hash表时,可以构建布隆过滤器来runtime filter,能少scan好多数据

runtime code generation

不懂啥, 反正牛b就对了,用了这项优化技术,快了很多

I/O管理

impala可以很高效的从hdfd检索数据,为了提高scan的性能,impala使用了一个hdfs的功能,叫做short-circuit local reads

来 绕过datanode当从本地磁盘读数据时,快就完事了,后面也看不懂,反正I/O性能很强

Storage Formats

impala支持好多中存储格式,avro、parquet等,并且可以使用多种压缩策略。建议使用parquet

 下面时给的测试结果,parquet+snappy压缩效率不仅最好,查询还是最快的,好像只测了snappy压缩

 

评估

单用户和别的系统对比

ROADMAP

impala对sql支持比较完整,但MINUS and INTERSECT; ROLLUP and GROUPING SET仍然不支持,date/time/datetime数据类型也不支持,但以后可能会支持,后面都是些impala未来的规划了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值