天天看点

impala+kudu优化

打开网易云,准备tnd哭
           

目录

1.timestamp类型

2.统计信息

3.看懂执行计划

4.临时表使用parquet

5.join方式&join顺序

6.not in 

7.写kudu

1.timestamp类型

把日期字段转为timestamp类型,+日期函数,性能不是一般的赞,注意:kudu中timestamp和impala中的timestamp存储格式不一致,不要将timestamp类型字段作为主键,之前在cdh5.16上,以timestamp作主键,impala往该表写,造成impala服务宕了,后来加了才解决,这2参数后面7.写kudu会介绍

impala+kudu优化
impala+kudu优化

2.统计信息

join多的情况下,将每个表执行compute stats 表名,impala优化器会选择一种最优的方式去join(有时不一定是最优解),单表的话就别浪费资源来获取统计信息了

compute stats会将表每个字段都执行以下

impala+kudu优化

ndv类似count(distinct field),前者是估值,所以表大的话,执行特别耗时,

impala+kudu优化

100多G的表,耗时3分钟

示例:执行前先看执行计划

impala+kudu优化

三张表的行数

t6:39668698  t1:119764290  a:67694913

impala+kudu优化

可以看到(后面3会介绍执行计划,相比spark、hive,impala的执行计划真的贼清晰了), a表被广播了,6kw的一个表,最上面有警告,

有1个表没统计信息,就是被广播的那个,impala默认会将表广播(类似hive、spark的map join),所以获取完a表的统计信息,再次查看执行计划

impala+kudu优化

partitioned join,完美了 

3.看懂执行计划

示例sql:哈哈,一般我不会写from后跟多表的,就以下面为例吧

impala+kudu优化

查看执行计划

impala+kudu优化

涉及到表的数据量如下:

c 2.3亿、e 89、b 4000w、a 1.2亿、d 25000

执行计划是从下往上看:

  1. 扫描c表,并shuffle, exchange[hash(c.proposalno)]类似MR的shuffle,就是一个partiton&网络fetch的过程
  2. 扫描b表,并shuffle,因为b表要与c表关联,所以shuffle的key也是proposalno
  3. b、c关联
  4. 扫描a表,exchange[broadcast],意味着会将a表广播到所有节点 因为a表是4000w的大表,所以这里需要调整,调整为shuffle join
  5. b、c关联的结果与a表关联
  6. 扫描d表,exchange[broadcast],将d表广播到所有节点
  7. d表与前面关联的结果集关联
  8. 扫描e表,exchange[broadcast],将e表广播到所有节点
  9. e表与前面关联的结果及关联
  10. aggregate count(*),每个节点聚合子结果集的行数,
  11. 协调节点,(jdbc串连impala指定哪个节点,哪个节点就是协调节点),merge,合并别的节点发送过来的行数,就是最终结果了

上面就是在命令行或者jdbc工具(hue、dbvisual)等可以在执行前查看执行计划来看多表关联的时候是否有大表被广播,join优化目的也是要防止大表被广播

如果sql已经在执行,也可以去协调节点:25000去查看图形化界面

impala+kudu优化
impala+kudu优化

就是刚命令行执行计划的可视化界面,不过可以等sql执行完成后,查看各表关联后的行数,也可以summary查看每一步的预估资源和实际使用资源 

4.临时表使用parquet

对于没有delete、update的dw层或非ods层的表,使用parquet格式

impala+kudu优化
impala+kudu优化

parquet 250s

impala+kudu优化
impala+kudu优化

接近400s 

5.join方式&join顺序

impala+kudu优化

务必在多表关联sql前首先执行explain query,防止大表被broadcast

impala+kudu优化

可以看到虽然impala的优化器有所有表的统计信息,但还是把t1表给广播出去了,

t1表是一张1亿+行的表,优化器优化的关联顺序方式不一定是最优的,我们需要手动指定下关联方式,将sql改为如下:

impala+kudu优化

加在t6、t1之间加join [shuffle],注意:t6必须在前边,如果t1在前边,不生效,关联方式还是broadcast

这种我们只是指定了这两张表的关联方式,impala优化器依然会给我们优化关联顺序、和方式,我们可以在select后面加 straight_join,不让impala优化器来优化,按sql的书写顺序来关联表

impala+kudu优化

按我们的书写顺序来看,t1表先与a表以broadcast方式关联,将a表广播,然后结果再与

t6以broadcast方式关联,将t6表广播

查看执行计划:

impala+kudu优化

 与书写顺序一致,当使用straight_join时,需要手动将表排序,原则是先最大表,然后最小表,次小表,次次小表......直到所有表关联完 ,尽量保证中间物化结果最小,left deep tree 

6.not in 

impala not int默认将右表广播,而且没法指定partitioned join ,使用left anti join 

7.写kudu

impala+kudu优化

参考自

https://docs.cloudera.com/documentation/enterprise/5-16-x/topics/impala_kudu.html#kudu_dml

大致意思是:从CDH5.12/Impala2.9开始,写数据到kudu表自动添加一个exchange和一个sort节点到执行plan(疑问:只添加2个节点干这事?那这2个节点肯定会大量的网络I/O和内存消耗,势必会成为性能瓶颈),为了根据目标表的分区/主键来partition和sort数据,因为kudu在写入的时候会partition和sort,所以impala预分区/排序能降低kudu负载并且防止大批量的insert超时(疑问:应该可以避免kudu超时,impala预处理好数据kudu直接刷盘)。然而,这种默认行为可能降低写入数据时end-to-end性能(不让impala预处理,刚执行写入没多久,目标表就可以select出数据,让impala预处理,可能很长时间后,才能select到),从CDH5.13/Impala2.10起,可以使用、让impala不预排序、分区数据。

示例均为目标表不存在, 如果目标表存在的话,直接insert即可

impala+kudu优化
impala+kudu优化

 记得调大点kudu的内存