Impala性能优化
Impala优缺点:
核心组件:
- Statestore Daemon
该进程负责搜集集群中Impalad进程节点的健康状况,它通过创建多个线程来处理Impalad的注册订阅,并与各节点保持心跳连接,不断地将健康状况的结果转发给所有的Impalad进程节点。一个Impala集群只需一个statestored进程节点,当某一节点不可用时,该进程负责将这一信息传递给所有的Impalad进程节点,再有新的查询时不会把请求发送到不可用的节点上。
- Catalog Daemon
Impala目录服务组件将Impala SQL语句产生的元数据更改通知到群集中的所有DataNodes上。避免了通过Impala发出的SQL语句执行时产生的元数据更改,需要发出REFRESH和INVALIDATE METADATA语句才能生效。当您通过Hive创建表,加载数据等时,您需要在Impala节点上执行REFRESH或INVALIDATE METADATA,然后才能执行查询。
- Impala Daemon
它是运行在集群每个节点上的守护进程,是Impala的核心组件,在每个节点上这个进程的名称为Impalad。该进程负责读写数据文件;接受来自Impala-shell、Hue、JDBC、ODBC等客户端的查询请求(接收查询请求的Impalad为Coordinator),Coordinator通过JNI调用java前端解释SQL查询语句,生成查询计划树,再通过调度器把执行计划分发给具有相应数据的其它节点分布式并行执行,并将各节点的查询结果返回给中心协调者节点Coordinator,再由该节点返回给客户端。同时Impalad会与State Store保持通信,以了解其他节点的健康状况和负载。
- Impala Shell
提供给用户查询使用的命令行交互工具,供使用者发起数据查询或管理任务,同时Impala还提供了Hue、JDBC、ODBC等使用接口。
CDH优化:
- Impala daemon内存限制
对于一个Impala查询来说,用户可以设置 Memory Limit(mem_limit参数),就是这个查询在单个Impalad节点上能用到的内存上限,如果查询在某个节点超过了这个上限会被直接报错返回。如果用户不设置,默认使用Pool的Default Query Memory Limit,如果Pool没有设置,Impala会自己来估计这个值。据我们的使用经验来说,Impala自己估计的值非常不准确(如果表有统计信息会好一些,但还是很不准)。所以建议用户根据查询大小和复杂程度设置这个值。
mem_limit参数对查询的影响很大,例如一个查询set mem_limit = 10G,有30台Impalad节点,Impala就会认为这个查询会用到10G * 30 = 300G内存。如果Pool的剩余内存目前小于300G,查询就会被Queue住等待资源。所以mem_limit如果设置的太大会浪费内存,导致并发度降低;如果设置的太小会导致查询失败。
- StateStore 工作线程数
内存参数的设置:https://blog.csdn.net/qq_18882219/article/details/78447558
- 查询优化
查询语句优化: https://blog.csdn.net/github_32521685/article/details/103456683
https://blog.csdn.net/github_32521685/article/details/103444357
Impala性能优化要点:
1. 为数据存储选择合适的文件格式(如:Parquet)
通常对于大数据量来说,Parquet文件格式是最佳的,推荐用Snappy算法压缩。
2. 防止入库时产生大量的小文件(insert ... values会产生大量小文件,应该避免使用)。在impala外生成数据时,最好是text格式或者Avro,这样你就可以逐行的构建文件,到了impala之后,再通过简单的insert ... select语句将其转换为Parquet格式。
3. 根据实际的数据量大小选择合适的分区粒度
合适的分区策略可以对数据进行物理拆分,在查询的时候就可以忽略掉无用数据,提高查询效率,通常建议分区数量在3万以下。(太多的分区也会造成元数据管理的性能下降)
4. 为分区key选择最小的整数类型
虽然使用string类型也可以作为分区key,因为分区key最后都是作为HDFS目录使用,但是使用最小的整数类型作为分区key可以降低内存消耗
5. 选择合适的Parquet块大小
默认情况下,Impala的insert ... select语句创建的Parquet文件都是每个分区256M(在2.0之后改为1G了),通过Impala写入的Parquet文件只有一个块,因而只能被一个机器当作一个单元进行处理。如果在你的Parquet表中只有一个或者几个分区,或者一个查询只能访问一个分区,那么你的性能会非常慢,因为没有足够的数据来利用Impala并发分布式查询的优势。
6.在追求性能或者大数据量查询的时候,要先获取所需要的表的统计指标(如:执行compute stats),能缩短很多查询时间。
Set DISABLE_UNSAFE_SPILLS=0; (指定允许内存不足的情况下写磁盘IO)
全局计算统计:
compute stats table_name;
增量计算统计:(根据指定分区)
COMPUTE INCREMENTAL STATS table_name PARTITION (pt=’2019-12-02’)
7. 最小化将结果传回客户端的开销
使用以下技术:
- 聚合 如果需要知道有多少行与某个条件匹配、某列中的匹配值的总数、最低或最高匹配值等,请用聚合函数,count()、sum()、MAX(),不要把结果集发送到应用程序中计算。(未聚合结果集的规模可能很大,需要大量时间才能在网络上传输)
- 过滤 用where 查询的子句以消除不相关的行。
- limit 如果不要求完整的结果集,用limit加予限制。
结果集禁止使用美化格式进行展示(在通过impala-shell展示结果时,添加这些可选参数:-B、 --output_delimiter)
8. 确认查询是以高效的逻辑方式进行规划
在执行之前使用EXPLAIN来查看逻辑规划,分析执行逻辑。
- 增加更多的Impala节点
事实证明更多的Impala节点会显著地提高性能,这跟Hadoop使用更多的datanode提高性能是一样的。拥有更多的节点会让数据分散到更多的节点上,在执行查询的时候能够分发更多的任务并行执行,从而提高整体执行性能。
执行查询时优化内存的使用 在启动Impala守护进程的时候可以使用-mem_limits参数来限制内存消耗,这个参数只对查询(query)进行内存限制。
查询的执行依赖于内存 如果数据集太大以至于超出了机器的可用内存,这个查询将会失败。Impala对内存的使用并不直接根据数据集的大小决定,它是根据查询的类型而变化的。聚合查询需要的内存跟group之后的数据量一样,连接查询(join)需要的内存量等价于除开最大表之外的所有表的总大小。
采用资源隔离 如果你使用的是Cloudera Manager,可以使用Cloudera Manager的设备控制器(cgroups)机制来实现资源隔离(resource isolation)。
查询优化的步骤:
- 尽量少使用 invalidate metadata,尽量用REFRESH TABLE_NAME。
- 的确是集群的内存不足就该加内存了。
- 就是集群中内存足够,只是impala在生成查询计划时,计算的内存使用量比实际需要量小,这个对依赖的表都加上 compute stat 语句,这样impala 在生成查询计划时就能更准确的计算资源使用量。
- 在执行完成统计信息命令后,使用SHOW TABLE STATS table_name命令,检测确认统计信息是否可用,输出表的详细统计信息。
Summary
Profile:(本命令可以查看上次SQL运行的过程,可以查看哪里比较耗时)
Compute stats his_stl_txn_dtl;(统计表结构信息)对全表统计可能会花很长时间(出现假死情况)。
Show table stats his_stl_txn_dtl;(查看统计的表结构信息)
通过explain命令可以预评估将要执行的SQL语句的执行过程和需要的资源(比如所需的内存、VCores)。
优化表结构之后:
Est表示估值,预计,例:
Peak Mem表示本次运行SQL的实际峰值。
Est. Peak Mem表示运行本次SQL预估峰值。