impala的sql执行优化过程

文章分两部分

1 基于impala的sql执行优化过程

2 Impala+kudu架构的数据仓库经验分享

第一部分,sql调优

1.老生常谈,sql调优必看执行计划,无论是hive还是impala。查看impala的执行计划可以说比较详细,分为三个粒度,分别是:explain、summary、profile。
(1) impala-shell中执行explain sql,会打印sql语句的执行计划,每一步的解释如下图所示:
impala的sql执行优化过程

优点:查看执行计划,调整sql语句
缺点:不清楚sql的执行详情,调整sql语句只能凭经验

(2) 在sql执行完成后,执行summary可以 看到这条sql语句执行时所消耗的时间和资源的情况,还有Impala预估的资源使用
执行summary语句后打印情况如下图:
impala的sql执行优化过程

优点:明确sql每个阶段的执行时间以及资源占用情况,和具体的关联方式
缺点:执行复杂的sql可能会耗费长时间,只能在sql执行后查看明细

(3)sql执行完成后,执行profile,产生一个详细的报告显示低水平的最新查询被执行。此信息仅在查询完成后才可用。它显示物理细节,如读取字节数、最大内存使用量等每个节点的物理细节,部分显示如下图:
impala的sql执行优化过程

优点:使用此信息来确定如果查询是I/O密集型或CPU绑定的,是否有网络条件实施的瓶颈,是否放缓是影响而不是其他的一些节点,并检查推荐配置设置,如短路本地读取效果
缺点:打印输出的明细数据量非常大,不太容易查看

根据以上三类语句,基本上可以分析清楚sql的执行情况,以及每个阶段所消耗的执行时间和资源情况,就可以找出拖累整体运行效率的执行片段,定位到具体环节,针对此过程进行优化就会大大的提高整体sql脚本的执行效率。

优化的侧重点主要有一下几个方面:

  1. 结合执行计划,进行Join 时防止大表被广播。
  2. 根据实际情况调整关联方式: broadcast 、(Shuffle)partitioned join
    broadcast 适合大表关联小表,将小表广播复制到各个节点,再和左表进行JOIN
    (Shuffle)partitioned join 适合大表和大表关联. 注意 partitioned join 和右表的 partition 没有直接关系, impala 会将右表打散成N份, 发送到左表所在的节点, 然后作join
  3. 要写入大量数据时,尽量使用Kudu的API直接写入,采用impala写入时,impala会进行预分区/排序来降低Kudu的负载,并防止大批量的insert超时,but,正是由于这种机制存在,会降低写入数据时 end-to-end 的性能(impala预处理,在执行很长时间后才能查到数据,不让impala预处理,目标表很快就能查到数据),从CDH5.13/Impala2.10起,可以使用/* +NOCLUSTERED*/、/NOSHUFFLE /让impala不预排序、分区数据。
    例如 insert into table_a /
     +NOCLUSTERED
    /,/*NOSHUFFLE */ select * from table_b

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

  1. 定期对表收集统计信息, 或者在大量DML操作后主动收集统计信息. 执行 COMPUTE STATS table,需要注意的是此语句在进行大表操作时会耗费相当长的时间
  2. 使用not in,not exists 默认将右表广播,而且没法指定partitioned join ,使用left anti join
  3. 使用 straight_join 进行自定义表的关联顺序,不按照impala优化器的优化顺序执行
  4. 根据 summary 的结果,确定出需要优化的位值,减少关联数据量和表字段
    (各位大佬有其他途径或者方法,希望留言告知,非常感谢)

第二部分,Impala+kudu架构的数据仓库经验分享

impala + kudu 在数据仓库中需要注意的点:(浅谈经验)

  1. kudu表的类型及其优缺点 range分区 如果创建时间序列的分区,分区忘记创建容易导致数据写入失败 Hash分区会导致数据表越来越大,查询检索性能收到影响
  2. kudu 进行大批量的delete效率低,并且集群产生垃圾较多(必要时候直接drop,再create,效率会更高,空间也会释放)
  3. 在进行数据仓库分层统计时,应保持相应的数据一致性,这个是kudu目前发现的比较鸡肋的点,就是没有overwrite 功能,不能重写,不能truncate table/partitions。
 在数据处理过程中,会出现如下情况:
       第一次写入数据为10条
       由于当第一次计算错误。
       第二次计算将新结果写入时,用upsert只会更新和添加与第一次主键重复或者新增的数据,比如更新了8条,那么表里会有两条脏数据,没法处理。
 这种情况有两种方式处理:
       第一,当数据为中间结果表,量级小时可以采取的措施要么进行drop或者delete,清空或者重建表重新插入。
       第二,在新数据插入/更新之前,将表中的数据进行标记删除,之后插入的数据会更新标记,此操作相对合理
       
(另一种方式可以借助 Parquet 列式存储格式的hive表,Impala+Parquet 查询性能也是非常快,并且可以使用overwrite,避免产生数据垃圾) 
    1. 在执行ETL操作前,尽可能执行compute stats 表名,不然impala执行sql生成的计划执行数评估的内存不准确,容易评估错误导致实际执行不了

    2. 查看kudu表分区下所占的存储空间 和表总的存储空间
      a.查看表整体所占用的存储空间,如下图:
      impala的sql执行优化过程

      b.查看表分区所占的存储空间
      Cloudera Manager -->进入Kudu --> 进入Web UI–如下图:
      impala的sql执行优化过程
      进入Tablet Servers之后就能查看集群节点的Tablet Servers详情列表,如下图
      impala的sql执行优化过程
      进入任意一个Tablet Servers后,能够查到具体的表对应的分区大小,如下图:
      impala的sql执行优化过程

上一篇:kudu性能优化


下一篇:kudu官网学习。