Impala是Cloudera在受到Google的Dremel启发下开发的实时交互SQL大数据查询工具(实时SQL查询引擎Impala),Impala没有再使用缓慢的Hive+MapReduce批处理,而是经过使用与商用并行关系数据库中相似的分布式查询引擎(由Query Planner、Query Coordinator和Query Exec Engine三部分组成),能够直接从HDFS或HBase中用SELECT、JOIN和统计函数查询数据,从而大大下降了延迟。前端
Impala架构如图所示java
Impala主要由Impalad, State Store和CLI组成。python
Impalad: 与DataNode运行在同一节点上,由Impalad进程表示,它接收客户端的查询请求(接收查询请求的Impalad为Coordinator,Coordinator经过JNI调用java前端解释SQL查询语句,生成查询计划树,再经过调度器把执行计划分发给具备相应数据的其它Impalad进行执行),读写数据,并行执行查询,并把结果经过网络流式的传送回给Coordinator,由Coordinator返回给客户端。同时Impalad也与State Store保持链接,用于肯定哪一个Impalad是健康和能够接受新的工做。算法
在Impalad中启动三个ThriftServer: beeswax_server(链接客户端),hs2_server(借用Hive元数据), be_server(Impalad内部使用)和一个ImpalaServer服务。数据库
Impala State Store: 跟踪集群中的Impalad的健康状态及位置信息,由statestored进程表示,它经过建立多个线程来处理Impalad的注册订阅和与各Impalad保持心跳链接,各Impalad都会缓存一份State Store中的信息,当State Store离线后(Impalad发现State Store处于离线时,会进入recovery模式,反复注册,当State Store从新加入集群后,自动恢复正常,更新缓存数据)由于Impalad有State Store的缓存仍然能够工做,但会由于有些Impalad失效了,而已缓存数据没法更新,致使把执行计划分配给了失效的Impalad,致使查询失败。后端
CLI: 提供给用户查询使用的命令行工具(Impala Shell使用python实现),同时Impala还提供了Hue,JDBC, ODBC使用接口。缓存
Impala与Hive都是构建在Hadoop之上的数据查询工具各有不一样的侧重适应面,但从客户端使用来看Impala与Hive有不少的共同之处,如数据表元数据、ODBC/JDBC驱动、SQL语法、灵活的文件格式、存储资源池等。Impala与Hive在Hadoop中的关系如图 2所示。Hive适合于长时间的批处理查询分析,而Impala适合于实时交互式SQL查询,Impala给数据分析人员提供了快速实验、验证想法的大数据分析工具。能够先使用hive进行数据转换处理,以后使用Impala在Hive处理后的结果数据集上进行快速的数据分析。网络
Impalad分为Java前端与C++处理后端,接受客户端链接的Impalad即做为此次查询的Coordinator,Coordinator经过JNI调用Java前端对用户的查询SQL进行分析生成执行计划树,不一样的操做对应不用的PlanNode, 如:SelectNode, ScanNode, SortNode, AggregationNode, HashJoinNode等等。架构
执行计划树的每一个原子操做由一个PlanFragment表示,一般一条查询语句由多个Plan Fragment组成, Plan Fragment 0表示执行树的根,汇聚结果返回给用户,执行树的叶子结点通常是Scan操做,分布式并行执行。并发
Java前端产生的执行计划树以Thrift数据格式返回给Impala C++后端(Coordinator)(执行计划分为多个阶段,每个阶段叫作一个PlanFragment,每个PlanFragment在执行时能够由多个Impalad实例并行执行(有些PlanFragment只能由一个Impalad实例执行,如聚合操做),整个执行计划为一执行计划树),由Coordinator根据执行计划,数据存储信息(Impala经过libhdfs与HDFS进行交互。经过hdfsGetHosts方法得到文件数据块所在节点的位置信息),经过调度器(如今只有simple-scheduler, 使用round-robin算法)Coordinator::Exec对生成的执行计划树分配给相应的后端执行器Impalad执行(查询会使用LLVM进行代码生成,编译,执行。对于使用LLVM如何提升性能这里有说明),经过调用GetNext()方法获取计算结果,若是是insert语句,则将计算结果经过libhdfs写回HDFS当全部输入数据被消耗光,执行结束,以后注销这次查询服务。
Impala的查询处理流程大概如图所示:
下面以一个SQL查询语句为例分析Impala的查询处理流程。如select sum(id), count(id), avg(id) from customer_small group by id; 以此语句生成的计划为:
PLAN FRAGMENT 0 PARTITION: UNPARTITIONED 4:EXCHANGE tuple ids: 1PLAN FRAGMENT 1 PARTITION: HASH_PARTITIONED: <slot 1> STREAM DATA SINK EXCHANGE ID: 4 UNPARTITIONED 3:AGGREGATE | output: SUM(<slot 2>), SUM(<slot 3>) | group by: <slot 1> | tuple ids: 1 | 2:EXCHANGE tuple ids: 1PLAN FRAGMENT 2 PARTITION: RANDOM STREAM DATA SINK EXCHANGE ID: 2 HASH_PARTITIONED: <slot 1> 1:AGGREGATE | output: SUM(id), COUNT(id) | group by: id | tuple ids: 1 | 0:SCAN HDFS table=default.customer_small #partitions=1 size=193B tuple ids: 0
执行行计划树如图所示, 绿色的部分为能够分布式并行执行:
一、没有使用MapReduce进行并行计算,虽然MapReduce是很是好的并行计算框架,但它更多的面向批处理模式,而不是面向交互式的SQL执行。与MapReduce相比:Impala把整个查询分红一执行计划树,而不是一连串的MapReduce任务,在分发执行计划后,Impala使用拉式获取数据的方式获取结果,把结果数据组成按执行树流式传递聚集,减小的了把中间结果写入磁盘的步骤,再从磁盘读取数据的开销。Impala使用服务的方式避免每次执行查询都须要启动的开销,即相比Hive没了MapReduce启动时间。
二、使用LLVM产生运行代码,针对特定查询生成特定代码,同时使用Inline的方式减小函数调用的开销,加快执行效率。
三、充分利用可用的硬件指令(SSE4.2)。
四、更好的IO调度,Impala知道数据块所在的磁盘位置可以更好的利用多磁盘的优点,同时Impala支持直接数据块读取和本地代码计算checksum。
五、经过选择合适的数据存储格式能够获得最好的性能(Impala支持多种存储格式)。
六、最大使用内存,中间结果不写磁盘,及时经过网络以stream的方式传递。
数据存储:使用相同的存储数据池都支持把数据存储于HDFS, HBase。
元数据:二者使用相同的元数据。
SQL解释处理:比较类似都是经过词法分析生成执行计划。
执行计划:
Hive: 依赖于MapReduce执行框架,执行计划分红map->shuffle->reduce->map->shuffle->reduce…的模型。若是一个Query会被编译成多轮MapReduce,则会有更多的写中间结果。因为MapReduce执行框架自己的特色,过多的中间过程会增长整个Query的执行时间。
Impala: 把执行计划表现为一棵完整的执行计划树,能够更天然地分发执行计划到各个Impalad执行查询,而不用像Hive那样把它组合成管道型的map->reduce模式,以此保证Impala有更好的并发性和避免没必要要的中间sort与shuffle。
数据流:
Hive: 采用推的方式,每个计算节点计算完成后将数据主动推给后续节点。
Impala: 采用拉的方式,后续节点经过getNext主动向前面节点要数据,以此方式数据能够流式的返回给客户端,且只要有1条数据被处理完,就能够当即展示出来,而不用等到所有处理完成,更符合SQL交互式查询使用。
内存使用:
Hive: 在执行过程当中若是内存放不下全部数据,则会使用外存,以保证Query能顺序执行完。每一轮MapReduce结束,中间结果也会写入HDFS中,一样因为MapReduce执行架构的特性,shuffle过程也会有写本地磁盘的操做。
Impala: 在遇到内存放不下数据时,当前版本1.0.1是直接返回错误,而不会利用外存,之后版本应该会进行改进。这使用得Impala目前处理Query会受到必定的限制,最好仍是与Hive配合使用。Impala在多个阶段之间利用网络传输数据,在执行过程不会有写磁盘的操做(insert除外)。
调度:
Hive: 任务调度依赖于Hadoop的调度策略。
Impala: 调度由本身完成,目前只有一种调度器simple-schedule,它会尽可能知足数据的局部性,扫描数据的进程尽可能靠近数据自己所在的物理机器。调度器目前还比较简单,在SimpleScheduler::GetBackend中能够看到,如今尚未考虑负载,网络IO情况等因素进行调度。但目前Impala已经有对执行过程的性能统计分析,应该之后版本会利用这些统计信息进行调度吧。
容错:
Hive: 依赖于Hadoop的容错能力。
Impala: 在查询过程当中,没有容错逻辑,若是在执行过程当中发生故障,则直接返回错误(这与Impala的设计有关,由于Impala定位于实时查询,一次查询失败,再查一次就行了,再查一次的成本很低)。但从总体来看,Impala是能很好的容错,全部的Impalad是对等的结构,用户能够向任何一个Impalad提交查询,若是一个Impalad失效,其上正在运行的全部Query都将失败,但用户能够从新提交查询由其它Impalad代替执行,不会影响服务。对于State Store目前只有一个,但当State Store失效,也不会影响服务,每一个Impalad都缓存了State Store的信息,只是不能再更新集群状态,有可能会把执行任务分配给已经失效的Impalad执行,致使本次Query失败。
适用面:
Hive: 复杂的批处理查询任务,数据转换任务。
Impala:实时数据分析,由于不支持UDF,能处理的问题域有必定的限制,与Hive配合使用,对Hive的结果数据集进行实时分析。
优势:
支持SQL查询,快速查询大数据。
能够对已有数据进行查询,减小数据的加载,转换。
多种存储格式能够选择(Parquet, Text, Avro, RCFile, SequeenceFile)。
能够与Hive配合使用。
缺点:不支持用户定义函数UDF。不支持text域的全文搜索。不支持Transforms。 不支持查询期的容错。对内存要求高。