Impala是由Cloudera公司开发的新型查询系统,参照Dremel系统进行设计的。提供SQL语义,能查询存储在Hadoop的HDFS和HBase上的PB级大数据,在性能上比Hive高出3~30倍。
基于Hive的大数据实时分析查询引擎,其运行需要依赖于Hive元数据。Impala采用与商用并行关系数据库类似的分布式查询引擎,可以直接与HDFS和HBase进行交互查询。Impala和Hive采用相同的SQL语法、ODBC驱动程序和用户接口。Impalad核心进程,负责接收查询请求并向多个数据节点分发任务。statestored进程负责监控所有Impalad进程,并向集群中的节点报告各个Impalad进程的状态。catalogd进程负责广播通知元数据的最新信息
特性:
劣势:
不同点:
相同点:
总结:
Impala和Hive、HDFS、HBase等工具是统一部署在一个Hadoop平台上的,主要由Impalad,State Store和CLI三部分组成:
说明:Impala中的元数据直接存储在Hive中。Impala采用与Hive相同的元数据、SQL语法、ODBC驱动程序和用户接口,从而使得在一个Hadoop平台上,可以统一部署Hive和Impala等分析工具,同时支持批处理和实时查询。
Impala执行查询的具体过程:
建表语句中的location指向实际数据的路径;
了解一个表的基本类别可以通过
show create table
命令;
删除impala的一行数据:不是delete
元数据是记录数据的数据。Impala的数据就是文件,而元数据是记录文件存在什么位置,多少个,大小,时间等。
invalidate metadata和refresh
refresh轻量级,适用于数据更新(不是Impala途径增加或者删除数据)的场景;
invalidate metadata,适用于表结构发生改变(非Impala途径创建或者修改表结构);
收集统计信息:
compute stats db.table
查看表统计信息:
show table stats db.table
查看字段统计信息:
show column stats db.table
用途:
join query缺少统计信息时,可能会生成错误的执行计划,查询缓慢;
join算法有两类:
broadcast,广播连接,Impala默认方式,大表一定要放在左边,因为impala在广播右侧表,所有右侧表会复制到需要右侧表进行联接的所有节点。右侧的表被认为比左侧的表小,并且它的内容被发送到查询涉及到的其他节点上。
在join后面加[shuffle],将broadcast join转换为shuffle join,
替代的技术称作分割连接(partitioned join,与分区表无关),更适用于近乎相同大小的大型表的连接,每一个表的部分内容被发送到对应的其他节点,然后这些行的子集可以并行处理。广播和分区连接的选择仍然依赖于连接中所有表的可用的、使用 COMPUTE STATS 语句的统计信息。
Impala join查询最简单的优化手段就是通过使用compute stats来收集join中每张表的统计信息,然后由Impala根据表的大小、列的唯一值数目等来自动优化查询。为了更加精确地获取每张表的统计信息,每次表的数据变更时(如执行insert、load data、add partition、或drop partition等)都要重新执行一遍
compute stats
。
若join查询中表的统计信息不全或者Impala选择的join顺序不是最优时,可在
select [distinct 、all]
后指定
straight_join
来覆盖掉impala的join顺序:
select straight_join x
from medium join small join (select * from big where c1 < 10) as big
where medium.id = small.id and small.id = big.id;
select distinct straight_join x
from medium join small join (select * from big where c1 < 10) as big
where medium.id = small.id and small.id = big.id;
这样Impala就会使用查询语句中表的顺序来指导join的处理。
使用STRAIGHT_JOI技术时,须手动指定join查询中表的顺序而不是依赖于Impala优化器。Impala优化器使用特殊的手段来估算join中每个阶段的结果集大小,而对于手动指定顺序来说,可以根据如下方式开始,然后再手动调节来达到最优:
如表的大小如下:BIG、MEDIUM、SMALL和TINY,那顺序应该如此:BIG join TINY join SMALL join MEDIUM。
Impala查询优化器根据表的绝对或者相对大小来选择不同技术来执行join查询。
broadcast或者partition join的选择是根据compute stats采集到的可用统计指标来衡量的。对于指定查询语句,可以通过执行EXPLAIN就可以查看选用的是哪个join策略。
当join中表或者列的统计指标不可用时,Impala将无统计指标的表认为统计指标都为0,这些表都将作为右表处理。
创建表时可通过指定location来指定表文件的存放路径,如果不指定的话,默认是将数据存放在
/user/hive/warehouse/库名
下。未被external修饰的表是内部表(managed table),被external修饰的是外部表(external table)
区别:
/user/hive/warehouse/目录
下(这个目录是可以在配置文件中修改的)。
收集信息使用
COMPUTE STATS
命令,查看信息使用
show table/column stats
。
和HIVE的ANALYZE TABLE类似,这个命令主要也是为了优化查询。本来IMPALA是依靠HIVE的ANALYZE TABLE的,但是这个命令不是很好用同时不稳定,所以IMPALA自己实现个命令完成相同功能。
有两类,语法:
# 全量
COMPUTE STATS [db_name.]table_name
# 增量
COMPUTE INCREMENTAL STATS [db_name.]table_name [PARTITION (partition_spec)]
作用:
收集有关表中数据的容量和分布以及所有相关列和分区的信息。这些信息存储在metastore数据库中,Impala使用这些信息来帮助优化查询。
区别:
COMPUTE STATS适用于全量,操作更重量级,适合非分区表;
COMPUTE INCREMENTAL STATS适用于增量,操作轻量级,适合分区表;
> show table stats t2;
| #Rows | #Files | Size | Format |
±------±-------±---------±-------+
| -1 | 28 | 960.00KB | TEXT |
> show column stats t1;
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
±-------±-------±-----------------±-------±---------±---------+
| id | INT | -1 | -1 | 4 | 4 |
| s | STRING | -1 | -1 | -1 | -1 |
通常对于大数据量来说,Parquet文件格式是最佳的
参考: 如何在Impala中使用Parquet表
ILIKE:忽略大小写的 like 操作符
REGEXP:正则匹配操作符
RLIKE:同 REGEXP 操作符
IREGEXP:忽略大小写的正则匹配符
IS DISTINCT FROM:判断前后两个表达式是否不相等,和
<>
操作符类似,但 null IS DISTINCT FROM null 返回 false
IS not DISTINCT FROM:判断前后两个表达式是否相等,和=操作符类似,唯一不同的是,处理 null 时候,null IS not DISTINCT FROM null 结果为 ture
set mem_limit=-1;
取消内存限制;
set DISABLE_UNSAFE_SPILLS=0/FALSE;
设置为
0/FALSE
时,内存运算濒临溢出时转为磁盘运算;
1/TRUE
时,当内存溢出时直接报内存溢出
Memory limit exceeded
错误
java.sql.SQLException:memory limit exceeded
常见原因:
在优化之前,可先拿到查询计划,类似
mysql explain
查询计划。在执行后也可以查看详细的执行信息。
Impala提供 三种 方式得知查询计划
EXPLAIN语句概述了查询将执行的逻辑步骤,例如如何在节点间分配工作以及中间结果如何合并为最终结果, 这些你都可以在查询真正执行之前获得,你可以使用这些信息来检查查询是否会以某种非高效的方式执行。
explain select ds,count(*) from t_ed_xxxx_newuser_read_feature_n group by ds order by ds;
| Max Per-Host Resource Reservation: Memory=9.94MB |
| Per-Host Resource Estimates: Memory=27.00MB |
| |
| PLAN-ROOT SINK |
| | |
| 05:MERGING-EXCHANGE [UNPARTITIONED] |
| | order by: ds ASC |
| | |
| 02:SORT |
| | order by: ds ASC |
| | |
| 04:AGGREGATE [FINALIZE] |
| | output: count:merge(*) |
| | group by: ds |
| | |
| 03:EXCHANGE [HASH(ds)] |
| | |
| 01:AGGREGATE [STREAMING] |
| | output: sum_init_zero(default.t_ed_xxxx_newuser_read_feature_n.parquet-stats: num_rows) |
| | group by: ds |
| | |
| 00:SCAN HDFS [default.t_ed_xxxx_newuser_read_feature_n] |
| partitions=372/372 files=2562 size=15.15GB
自底向上读取EXPLAIN的输出:
00阶段:显示了底层的详细信息,如:扫描的表,表的分区数,文件数以及文件大小等信息,根据这些信息,你可以估算大概的耗时
01阶段:聚合操作SUM并行地在不同的节点上执行
03阶段:将01阶段的结果进行传输
04阶段:将SUM结果进行合并
02阶段:排序操作并行地在不同的节点中进行
05阶段:排序结果合并,并且输出
EXPLAIN也会在PROFILE结果的头部输出。
SUMMARY命令可以输出每一阶段的耗时,可以快速地了解查询的性能瓶颈,与PROFILE输出一样,它只能在查询之后才可用,并且显示实际的时间消耗。SUMMARY输出也会在PROFILE的头部输出的显示。
select ds,count(*) from t_ed_xxxx_newuser_read_feature_n group by ds order by ds;
summary;
+---------------------+--------+----------+----------+-------+------------+----------+---------------+--------------------------------------------+
| Operator | #Hosts | Avg Time | Max Time | #Rows | Est. #Rows | Peak Mem | Est. Peak Mem | Detail |
+---------------------+--------+----------+----------+-------+------------+----------+---------------+--------------------------------------------+
| 05:MERGING-EXCHANGE | 1 | 3.20s | 3.20s | 372 | 372 | 0 B | 0 B | UNPARTITIONED |
| 02:SORT | 51 | 517.22us | 2.54ms | 372 | 372 | 6.02 MB | 6.00 MB | |
| 04:AGGREGATE | 51 | 1.75ms | 7.85ms | 372 | 372 | 2.12 MB | 10.00 MB | FINALIZE |
| 03:EXCHANGE | 51 | 2.91s | 3.10s | 2.44K | 372 | 0 B | 0 B | HASH(ds) |
| 01:AGGREGATE | 51 | 135.29ms | 474.62ms | 2.44K | 372 | 2.03 MB | 10.00 MB | STREAMING |
| 00:SCAN HDFS | 51 | 1.08s | 2.58s | 2.56K | 96.53M | 1.05 MB | 1.00 MB | default.t_ed_xxxx_newuser_read_feature_n |
PROFILE和SUMMAY区别
profile:输出底层信息计划
summary:查看查询时间及占用内存
区别不重要,都可用。
除了查询计划,最佳实践:
insert ... values
会产生大量小文件,应该避免使用)
insert ... select
语句将其转换为Parquet格式.
insert ... select
语句创建的Parquet文件都是每个分区256M(在2.0之后改为1G),通过Impala写入的Parquet文件只有一个块,因而只能被一个机器当作一个单元进行处理。如果在你的Parquet表中只有一个或者几个分区,或者一个查询只能访问一个分区,那么你的性能会非常慢,因为没有足够的数据来利用Impala并发分布式查询的优势。
compute stats
)
-B, --output_delimiter
)
具体地:
参考Excel连接Impala
RuntimeFilter 是Impala 2.5及更高版本中可用的优化特性 。当针对分区表进行查询,或join条件仅需要表中的一小部分数据时,Impala会在查询运行时确定适当的条件,并将该信息广播到所有正在读取数据的impalad节点,以便它们可以避免不必要的IO,并仅输出与之匹配的数据子集来避免不必要的网络传输。
Impala高性能探秘之Runtime Filterkudu pk parquet—runtime filter实践
Impala - Runtime Filter的原理及实现
Impala技术原理
Impala的命令COMPUTE STATS
Impala性能优化总结
Apache Impala 性能优化