
测试思路
从单表开始,区分外部表与内部表,进行count、group by等
多表关联,join
测试过程
一、 单表测试 (选取外部表 :weblog.clicklog)
测试sql
1 | select count(distinct t.id) from test.log t where t.day >= '20180101' |
注:impala里不是默认数字为字符串,表中day类型为string,故必须加引号,hive里不需要;
在执行sql程序时,需要查看表结构和表列结构,以及sql查询的执行计划
1 | SHOW TABLE STATS test.log; // 查看表结构 |
1 | SHOW COLUMN STATS test.log; // 查看表列结构 |
1 | explain select count(*) from test.log t -- 查看sql执行计划 |
注:如果表每日都会更新时,需要对impala中的表更新,才能与hive中的表同步;
impala与hive同步
1 | INVALIDATE METADATA; //重新加载所有库中的所有表 |
- 使用原则
如果在使用过程中涉及到了元数据或者数据的更新,则需要使用这两者中的一个操作完成,具体如何选择需要根据如下原则:
- invalidate metadata操作比refresh要重量级;
- 如果涉及到表的schema改变,使用invalidate metadata [table],eg:在hive中create表后,需要在impala使用invalidate metadata [table];
- 如果只是涉及到表的数据改变,使用refresh [table];
- 如果只是涉及到表的某一个分区数据改变,使用refresh [table] partition [partition];
- 禁止使用invalidate metadata什么都不加,宁愿重启catalogd;
测试结果
impala
1 | [master3.xxx:21000] > select count(distinct t.id) from test.log t where t.day >= '20180101'; |
hive
1 | hive> select count(distinct t.id) from test.log t where t.day >= '20180101'; |
从测试结果上看,两者从运行速度上并没有什么差别,没有网上说的比hive有十倍或者十几倍的差距;
故考虑impala的性能优化
impala性能优化
目前从表结构以及执行计划中发现的,并结合网上查找的资料,进行以下两点优化,以后对impala有更深的了解后,再进行补充:
1. 表的存储结构
从SHOW TABLE STATS命令中可以发现 表的format,上述测试的test.log的format是TEXT;
在网上查找资料,参考hive表的文件存储格式
发现parquet格式与impala组合会提高表的查询效率,故测试建立parquet存储格式的临时表;
1 | -- hive |
表的存储格式修改后,impala的查询效率确定有提高,从56.25s 到 2.50s ;
2. 表信息计算
在explain命令中,查看执行计划中发现里面存在warning,在网上查找资料,了解warning内容;
1 | WARNING: The following tables are missing relevant table and/or column statistics. |
大致意思应该是缺失对表的表信息与列信息的统计数据;
当统计信息可用时,Impala 可以更好的优化复杂的或多表查询,可以更好地理解数据量和值的分布,并使用这些信息帮助查询并行处理和分布负载。这里impala提供里对表信息更详尽统计的命令:
1 | COMPUTE STATS tablename; //对于不分区的表,或者虽然分区,但一次加载,不会再更新新分区的表,使用COMPUTE STATS更好 |
二、表关联查询 (join)
选取表:temp_parquet_log_20180209 、parquet_user(存储格式为parquet的用户信息表)
测试sql
1 | -- impala |
这里,我已经对两个表进行了compute table的处理,可以看出效率比hive高,但是,我们在查询之前却没有看sql的执行计划,看是否还有调优的地方;
join调优的原则
- 最大的表放首位。这个表在查询的时候是每个impala节点直接从磁盘读取的,因此它的大小对于内存使用没影响。
- 然后按表大小有大到小依次排序。这些表的内容全部都是要在网络中传递的,所以,表越到后面越小越好。
- 通过执行COMPUTE STATS来收集涉及到的所有表的统计信息
值得注意的一点是,这里的“大小”是就每个表在查询后生成的中间结果涉及到的行的数量来定的。比如,一次查询,要join两个表:销售表和用户表。查询的结果是100个不同的用户共有5000条消费记录。因为涉及用户表的行比销售表少(100<5000)。所以用户表应该放在后面(右边)
join调优
1 | -- 执行查询计划 |
从执行计划里可以看出,第二步 hash关联中,是由 用户表中的id 关联 轨迹日志中的id,并不是由轨迹日志(大)到 用户表(小);
impala中提供了一个straight_join关键词,手动调整关联顺序,即按照sql语句的顺序,而不采用impala中自动优化查询;
1 | explain select straight_join u.province_name,count(distinct t.id) nums |
最后测试结果又比之前提高了一倍,15.67s 到 7.25s;