前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文读懂Impala统计信息相关知识

一文读懂Impala统计信息相关知识

作者头像
skyyws
发布2022-05-20 08:43:37
1.3K0
发布2022-05-20 08:43:37
举报

Impala 4.0源码解析之BROADCAST/SHUFFLE代价计算这篇文章中我们提到,Impala在对BROADCAST/SHUFFLE进行代价计算的时候,需要用到表的统计信息。关于Impala的统计信息,网上也有一些资料介绍,但是大多不全。本文将结合官方文档,从内容、计算等各方面尽可能详细地介绍下Impala统计信息的相关知识。

统计信息介绍

目前来看,Impala的统计信息主要分为两种:表级别和列级别的。我们分别来看下这两种统计信息有何不同。

表级别统计信息

当我们执行SHOW TABLE STATS 的时候,Impala会返回这个表的相关统计信息,这里我们以Impala自带的functional_parquet.alltypes测试表为例,如下所示:

我们结合上述截图,分别看下每列的具体含义:

  • 分区列信息,这里的year和month都是分区列,多个分区列,则会按照SQL定义的顺序依次展示,图中每一条记录都代表一个具体的分区信息,例如第二行就对应分区year=2009/month=1;
  • Rows,表示记录数,分区表会统计每一个分区的记录数,最后一行会统计整个表的行数,如果是非分区表,则只有一行记录;
  • Files,表示文件数,统计每一个分区路径下的文件数,最后一行统计整个表的文件数;
  • Size,表示文件的字节数,统计每一个分区路径下的文件大小,最后一行统计整个表的文件大小;
  • Bytes Cached,如果表使用了hdfs cache的话,那么这一列就会统计缓存的字节数,可以通过:ALTER TABLE name PARTITION (partition_spec) SET { CACHED IN ‘pool_name’ WITH REPLICATION = integer | UNCACHED }来开启表/分区的hdfs cache特性,更多功能可以参见:Using HDFS Caching with Impala,这里不再展开;
  • Cache Replication,hdfs cache的副本数,可以在上述SQL中显示设置;
  • Format,分区的文件格式,对于hdfs表,不同的分区可以有不同的格式,例如parquet、orc、text等;
  • Incremental stats,表示分区是否进行了增量的统计信息计算,即是否执行了COMPUTE INCREMENTAL STATS,这个我们后面会专门介绍关于统计信息的计算;
  • Location,分区在HDFS上的路径;

对于分区表而言,执行SHOW PARTITIONS 结果与上述一样。但是如果是非分区表,则会直接报错。需要注意,这里是以hdfs表为例,如果对kudu表执行SHOW PARTITIONS,结果则不一样,如下所示:

如果表没有计算统计信息,那么结果就是这样的:

可以看到,Rows这一列都是-1,但是Files和Size仍然是有数据的。

列级别统计信息

上面我们介绍了表级别的统计信息,现在我们来看下列级别的统计信息是什么样的。当我们执行SHOW COLUMN STATS 的时候,Impala会返回这个表的各个列的统计信息,这里我们以tpch.customer为例,如下所示:

这里一共有8列值,我们分别介绍下每一列的含义:

  • Column,表的各个列的名称;
  • Type,表的各个列的类型;
  • Distinct Values,表示对应列的distinct值;
  • Nulls,表示对应的列中,null的数量;
  • Max Size,对应列中所有value的最大size,通过length函数计算长度。一般对于定长类型,例如int/bigint等,size都是固定的,包括下面的avg size;
  • Avg Size,对应列中所有value的size平均值。对于定长类型来说,这个值和Max Size是一样的,对于string来说,则不一样;
  • Trues/Falses,对于boolean类型的列来说,这两列分别表示true和false的个数,对于其他类型的列来说,就是-1。

如果说表没有统计信息的话,我们执行上述的查询,结果如下所示:

可以看到,除了定长类型的Max Size和Avg Size,其他的值都是-1,表示不存在。

统计信息计算

上面我们分别介绍了表级别和列级别的统计信息,现在我们来看一下Impala是如何计算统计信息的。目前在Impala中主要就是通过COMPUTE STATS 语句来进行统计信息计算,主要分为以下几种情况:

  • 全表统计信息计算:COMPUTE STATS alltypes,这种会对整个表的所有分区、所有列进行统计信息计算,如果是分区表,并且分区数据很多的情况下,这个语句会执行的比较慢;
  • 分区统计信息计算:COMPUTE INCREMENTAL STATS alltypes PARTITION(year=2009,month>1);,即对指定的分区进行统计信息计算,这种一般适合分区表,每天增量更新分区之后,对更新的分区进行统计信息计算,当执行这个语句的时候,对应分区的“Incremental stats”属性就会变为true。如果SQL没有指定具体的分区,那么Impala会自动检测没有统计信息的分区,并进行统计信息计算;
  • 计算指定列的统计信息:COMPUTE STATS alltypes(id,bool_col),可以只对某一列或者某几列进行统计信息计算;
  • 数据采样计算统计信息:COMPUTE STATS alltypes TABLESAMPLE SYSTEM(10) REPEATABLE(1000),当表的数据非常大的情况下,我们可以通过采样的方式来进行统计信息计算,10表示采样的数据比例,1000是一个random seed,用于生成随机数选取要采样的文件。这种计算目前只针对hdfs表有效。并且Impalad需要配置enable_stats_extrapolation为true,或者给指定表增加属性impala.enable.stats.extrapolation为true;

更多关于COMPUTE STATS的用法,可以参考:COMPUTE STATS Statement。其实,Impala在进行统计信息计算的时候,就是提交了几条SQL来获取相应的信息,然后存储到hms中,我们以COMPUTE INCREMENTAL STATS alltypes PARTITION(year=2009,month=1) 为例,此时Impala会自动提交两条SQL,如下所示:

其中,第一条SQL就是按照分区进行分组count计算,用于统计每个分区的记录数;第二条SQL就是计算每一列的distinct、nulls等值。对于上述不同的情况,SQL也会有所调整,例如对于采样计算,会使用SAMPLED_NDV,对于指定的列,只会选择这些列进行计算等等。

还有一点需要注意,不要交替使用COMPUTE STATSCOMPUTE INCREMENTAL STATS,当我们要在两种计算方式之间进行切换的时候,先执行DROP STATS 操作来删除之前的统计信息,然后再切换到另外一种计算方式。当然,对于非分区表,如果使用了COMPUTE INCREMENTAL STATS,最终Impala也会自动替换成COMPUTE STATS的计算方式。

统计信息获取

接下来,我们再简单看下,当执行SHOW TABLE/COLUMN STATS时,我们是如何获取到统计信息的。当表第一次访问被加载的时候,catalogd会从hms获取相应的统计信息,然后缓存在内存当中,相关函数调用关系如下所示:

代码语言:javascript
复制
load(HdfsTable.java):1179
-loadAllColumnStats(Table.java):413
--getTableColumnStatistics(MetastoreShim.java)
-loadAllColumnStats(Table.java):419
--injectColumnStats(FeCatalogUtils.java):165
---updateStats(Column.java):72
----update(ColumnStats.java)

通过函数调用可以看到,Impala会去加载表的列统计信息。此时,catalogd中就已经缓存了表的元数据,同时会通过statestored广播到各个coordinator节点,每个coordinator节点的jvm中也会保存一份元数据信息。当我们执行SHOW TABLE/COLUMN STATS 的时候,就会根据对应的SQL,返回相应的信息,相关的函数调用如下所示:

代码语言:javascript
复制
getStats(JniFrontend.java):387
-getColumnStats(Frontend.java):1209
--doGetColumnStats(Frontend.java)
getStats(JniFrontend.java):391
-doGetTableStats(Frontend.java):1275
--doGetTableStats(Frontend.java)

FE在进行SQL解析的时候会判断是哪种类型的SHOW STATEMENT,根据不同的操作类型,调用不同的函数。目前主要支持如下的四种操作:

代码语言:javascript
复制
//common/thrift/Frontend.thrift
enum TShowStatsOp {
  TABLE_STATS = 0
  COLUMN_STATS = 1
  PARTITIONS = 2
  RANGE_PARTITIONS = 3
}

可以看到,除了TABLE和COLUMN操作之外,还支持PARTITIONS操作,RANGE PARTITIONS则是针对Kudu表。

统计信息Web页面提示

在Impala提供的web页面,我们可以查看text plan标签页,来判断表的统计信息是否完整,如下所示:

如果SQL中的多个表,都存在统计信息缺失的情况,也都会在这个warning里面一一显示。除了这个地方,我们查看对应表的SCAN HDFS节点执行计划,也会有对应的提示:

可以看到,rows、size等都是处于unavailable的状态,表示这些信息目前都是无法获取的。Impala的web页面提供了非常丰富的信息,可以为SQL诊断分析提供很好的依据。

总结

到这里,关于Impala统计信息的介绍就差不多了。总结一下,本文主要介绍了Impala的表级别、列级别的统计信息内容,以及几种不同场景下的统计信息计算,最后简单介绍了统计信息是如何获取的。总的来说,统计信息可以帮助Impala生成更优的执行计划,对于减少内存消耗也有一定的帮助,是非常重要的信息,对于其他的计算引擎也是一样。所以建议尽量保证对于一些大表、核心表,进行周期性地统计信息计算,以提高查询性能。

值得一提的是,Impala在3.x版本中增加了一个query option:disable_hdfs_num_rows_estimate,默认为false,表示允许hdfs表,在统计信息缺失的情况下进行行数的预估,主要就是根据列的avg size进行预估计算。相关的计算逻辑位于HdfsScanNode.getStatsNumRows()函数中,感兴趣的同学可以自行阅读源码。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 统计信息介绍
    • 表级别统计信息
      • 列级别统计信息
      • 统计信息计算
      • 统计信息获取
      • 统计信息Web页面提示
      • 总结
      相关产品与服务
      大数据
      全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档