Presto ANALYZE 语句详解:表与列统计信息收集指南
【免费下载链接】prestoThe official home of the Presto distributed SQL query engine for big data项目地址: https://gitcode.com/gh_mirrors/pre/presto
ANALYZE是 Presto 中用于收集表和列统计信息的 SQL 语句,这些统计信息(行数、空值数、去重值数、min/max 等)是查询优化器进行 Join 顺序选择、谓词下推等代价估算的关键输入。本文以 ANALYZE 官方文档 为核心,结合 Hive、Iceberg 连接器的实现源码与文档,完整讲解语法、WITH 属性、支持范围、实战示例及底层原理,帮助读者在 Presto 集群中正确、高效地维护统计信息。
语法(Synopsis)
ANALYZE table_name [ WITH ( property_name = expression [, ...] ) ]table_name:目标表名,支持catalog.schema.table三段式全限定名,也可使用当前 catalog/schema 下的简化名称。WITH子句:可选,用于传入连接器特定的属性(property),例如 Hive 连接器的partitions属性。
功能描述(Description)
ANALYZE用于收集指定表的表级与列级统计信息。需要注意当前实现的限制:
- 目前仅为基本类型(primitive types)收集列统计信息,复杂类型(如
ROW、ARRAY、MAP等)不会生成列级统计。 - 统计信息的具体种类由底层连接器决定。以 Hive 连接器为例,Hive 连接器文档 中列出的各类型统计项如下:
| 列类型 | 收集的统计信息 |
|---|---|
TINYINT/SMALLINT/INTEGER/BIGINT/DOUBLE/REAL/DECIMAL/DATE/TIMESTAMP | null 数量、distinct 数量、min/max 值 |
VARCHAR/CHAR | null 数量、distinct 数量 |
VARBINARY | null 数量 |
BOOLEAN | null 数量、true/false 值数量 |
列出可用的 WITH 属性
WITH子句可用的属性是连接器相关的。要查看当前 Presto 版本下所有连接器注册的 analyze 属性,可直接查询系统表:
SELECT * FROM system.metadata.analyze_properties该表由 AnalyzePropertiesSystemTable.java 实现,它继承自AbstractPropertiesSystemTable,数据来源是Metadata.getAnalyzePropertyManager().getAllProperties()——也就是把各连接器在启动时注册的 analyze 属性统一汇总后暴露给查询。因此,运行这条查询即可获得与当前部署连接器精确匹配的属性清单、类型与默认值。
支持的连接器
ANALYZE并非所有连接器都支持。根据官方文档,当前仅以下两个连接器支持:
- Hive 连接器:见 Collecting table and column statistics,支持对分区表按分区收集统计信息。
- Iceberg 连接器:见 Collecting table and column statistics,支持全表统计信息收集。
对其他连接器执行ANALYZE会得到不支持的错误。
实战示例(Examples)
1. 分析整张表
对当前 catalog/schema 下的表web收集统计信息:
ANALYZE web;2. 使用三段式表名
指定 catalog 与 schema,避免歧义:
ANALYZE hive.default.stores;Iceberg 表用法相同:
ANALYZE iceberg.default.stores;Iceberg 连接器文档中的示例为ANALYZE iceberg.tpch.orders;,即对tpchschema 下的orders表收集统计信息。
3. 指定 Hive 分区表的部分分区
对于 Hive 分区表,默认会分析全部分区;也可以使用WITH (partitions = ...)精确定位需要分析的分区。partitions属性是一个外层数组,其中每个内层数组代表一个分区的各分区键值,键值的顺序必须与表 schema 中分区键的声明顺序一致。
按单分区键(ds为分区键)分析两个日期分区:
ANALYZE hive.default.sales WITH (partitions = ARRAY[ARRAY['1992-01-01'], ARRAY['1992-01-02']]);按复合分区键(分区键为state和city两列)分析两组分区:
ANALYZE hive.default.customers WITH (partitions = ARRAY[ARRAY['CA', 'San Francisco'], ARRAY['NY', 'NY']]);Hive 连接器文档 给出的通用形式为:
ANALYZE hive.sales WITH ( partitions = ARRAY[ ARRAY['partition1_value1', 'partition1_value2'], ARRAY['partition2_value1', 'partition2_value2']]);以上语句会分别收集分区键为partition1_value1, partition1_value2与partition2_value1, partition2_value2的两个分区的统计信息。
4. Iceberg 表的全表分析
Iceberg 连接器目前只支持全表统计收集(且ANALYZE仅支持在 autocommit 模式下执行,参见 Iceberg 连接器文档 中的事务限制说明):
ANALYZE iceberg.default.stores;源码级原理:Hive 连接器的 partitions 属性
partitions属性由 HiveAnalyzeProperties.java 定义与解析,可以从中看到几个值得注意的实现细节:
- 属性名常量:
public static final String PARTITIONS_PROPERTY = "partitions";。 - 属性类型声明为
array(array(varchar)),即内层数组的每个元素都是字符串类型,这解释了为何日期分区值需要写成'1992-01-01'这样的字符串字面量。 getPartitionList(...)方法负责从解析后的属性 Map 中取出分区列表,未指定时返回Optional.empty()(表示分析全表/全部分区)。decodePartitionLists(...)会把分区值中的null替换为 Hive 默认分区值(HIVE_DEFAULT_DYNAMIC_PARTITION),保证动态分区场景下也能正确匹配;同时会将结果转换为 Set 去重。- 若属性中出现
null分区值,会抛出INVALID_ANALYZE_PROPERTY错误,提示 "Invalid null value in analyze partitions property"。
统计收集的执行入口
在 HiveMetadata.java 中,getStatisticsCollectionMetadata方法定义了ANALYZE执行时收集哪些统计:
- 列统计范围:排除分区列(
partitionedBy)与隐藏列(hidden)后的所有列;临时表使用getColumnStatisticMetadataForTemporaryTable,普通表使用getColumnStatisticMetadata(后者会通过 metastore 的getSupportedColumnStatistics确认该类型支持哪些统计项)。 - 表统计:
ANALYZE场景(includeRowCount = true)会额外收集行数(ROW_COUNT)。 - 结果封装为
TableStatisticsMetadata(columnStatistics, tableStatistics, partitionedBy),由引擎统一调度执行统计收集任务,最终写回连接器的 metastore。
Quick Stats 与 ANALYZE 的互补关系
对于尚未执行过ANALYZE的分区,Hive 连接器可以通过读取文件/表元数据(例如 Parquet footer)推断出行数、null 数和 min/max 等"快速统计"(Quick Stats),在查询规划阶段作为临时统计来源。其行为由以下属性控制(详见 Hive 连接器文档):
| 属性名 | 说明 | 默认值 |
|---|---|---|
hive.quick-stats.enabled | 是否启用 quick stats 收集;也可通过会话属性quick_stats_enabled动态开关 | false |
hive.quick-stats.max-concurrent-calls | quick stats 会并发构建,此参数控制最大并发调用数 | 见连接器配置 |
使用建议与注意事项
- 分析时机:在批量写入、数据导入或 ETL 完成后执行
ANALYZE,确保优化器基于最新统计信息生成执行计划;对于不断变化的分区,可针对性地分析近期写入的分区,而不是反复全表分析。 - 分区表的成本控制:Hive 大分区表上执行不带
partitions的ANALYZE会扫描全部分区,耗时与资源开销较大,应优先使用WITH (partitions = ...)精准定位。 - 连接器支持范围:目前只有 Hive 与 Iceberg 连接器支持
ANALYZE;在部署多连接器集群时,先通过SELECT * FROM system.metadata.analyze_properties确认目标连接器注册了哪些属性。 - 统计信息驱动优化:准确的统计信息直接影响 Join 顺序选择、聚合与扫描阶段的代价估算。若查询计划出现明显退化,可先检查相关表是否缺少统计信息(例如 Hive 表存在缺失统计信息的分区时,可结合 Quick Stats 属性临时补充)。
- 类型限制:列统计仅覆盖基本类型,复杂类型列不会产生列级统计,规划阶段对这类列的估算依赖表级信息或连接器默认值。
通过以上语法、示例与源码解析,读者可以在 Presto 中熟练运用ANALYZE维护表与列统计信息,为查询优化器提供准确的代价估算依据,从而提升大规模数据查询的执行效率。
【免费下载链接】prestoThe official home of the Presto distributed SQL query engine for big data项目地址: https://gitcode.com/gh_mirrors/pre/presto
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考