- 大数据
- 数据库
- 后端
【免费下载链接】presto
The official home of the Presto distributed SQL query engine for big data
本指南基于当前仓库中的官方版本发布说明 release-0.155.rst,系统梳理 Presto(当前仓库版本为 0.300-SNAPSHOT)0.155 版本在通用查询引擎、Hive 连接器与 SPI 层面的全部变更,并结合仓库源码验证底层实现原理。读完本文,你将掌握这些变更的来龙去脉,理解 grouping sets、IN 谓词、外连接等正确性修复背后的执行计划逻辑,以及内存记账、map 聚合内存优化、Parquet 新读器、Avro 文件格式支持等能力的实际落地方式。
版本定位与变更概览
Release 0.155 是 Presto 演进过程中的一个常规功能性版本,其变更横跨三大模块:
- General Changes(通用引擎):以正确性修复为主,附带内存记账调整、内存优化与协调节点(coordinator)CPU 开销削减;
- Hive Changes(Hive 连接器):修复 Parquet 新读器的 schema 演进问题、Hadoop KMS 相关类加载问题,并新增 Avro 文件格式支持;
- SPI Changes(插件接口):移除 legacy connector API,进一步收紧了连接器插件必须遵循的接口契约。
版本号 0.155 对应的是 2017 年左右的 Presto 发布节奏;当前仓库已演进到 0.300-SNAPSHOT(见 pom.xml),但下述 0.155 引入的能力多数至今仍在代码库中保留并持续完善,例如key_based_sampling系列会话属性(见 SystemSessionProperties.java),可以作为理解现代 Presto 行为演进的起点。
General Changes:查询正确性修复
本节是 0.155 的核心,四个正确性修复分别对应查询执行链路中的不同环节。
多个 grouping sets 解析为同一集合时结果错误
GROUP BY GROUPING SETS是 Presto 支持的多维聚合语法。当一条查询中多个 grouping set 经过规范化后解析为同一组分组列时(例如GROUPING SETS ((a, b), (a, b))或通过展开后产生重复集合的情况),0.155 之前会产生错误的聚合结果。
从源码结构看,grouping sets 的执行由GroupIdOperator承担:它以groupingSetMappings(每组映射将输入列映射到输出列)为基础,为每个 grouping set 生成独立的groupId块,再按groupId分组聚合(见 GroupIdOperator.java)。当多个 grouping set 映射到同一组列时,若去重与分组映射的处理顺序不当,就会导致行被归入错误的 group,从而产生错误结果。0.155 的修复即是在计划阶段/执行阶段对重复 grouping set 进行正确归一化处理。
map 与 IN 谓词组合时结果错误
map数据类型与IN谓词组合使用(例如WHERE map_col['k'] IN (1, 2))在 0.155 之前可能产生错误结果。这类问题通常源于类型转换与常量折叠阶段对 map 取值表达式的处理缺陷——map 下标取值为空(key 不存在)时的 NULL 语义在 IN 列表求值过程中被错误传播。该修复属于表达式求值层的正确性修正,测试上对应 presto-main 的表达式与谓词求值测试套件。
复杂连接条件的外连接编译失败
当外连接(OUTER JOIN)的 ON 条件较为复杂(例如包含多层函数嵌套或多种运算符组合)时,0.155 之前可能触发编译失败(compile failure)。Presto 的 join 执行默认走本地字节码生成路径(presto-bytecode模块负责字节码生成),复杂连接条件在代码生成时若出现类型转换或变量作用域处理缺陷,就会导致生成的字节码无法通过校验。0.155 修复了该编译路径,使复杂 join 条件可正常生成并执行。
提交阶段失败的错误信息改进
查询提交(commit)阶段发生失败时,0.155 改进了错误信息的可读性,使 DBA 与用户能够更准确地定位失败环节(例如是元数据提交、目录提交还是文件提交失败),降低排障成本。
General Changes:内存记账与聚合内存优化
内存记账修正:聚合、Top N 与 DISTINCT
0.155 修复了简单聚合(simple aggregation)、Top N 与 DISTINCT 查询的内存记账(memory accounting)问题。修复前这些查询算子实际占用的内存可能未被完整计入,导致内存管理在压力下不够准确;修复后这些查询可能报告比以前更高的内存使用量——这是记账口径变准确的直接体现,而非新的内存泄漏。在presto-main-base的MemoryTrackingContext与各算子updateMemory调用链中可以看到现代版本对内存记账的持续强化。
减少 map_agg / multimap_agg / map_union 的不必要内存占用
map_agg、multimap_agg与map_union三个聚合函数在 0.155 中通过复用中间状态与减少临时对象分配,降低了内存占用。以 MapAggregationFunction.java 为例,它通过MethodHandle注册 input/combine/output 三阶段函数并使用专用 accumulator 状态累积键值对;MultimapAggregationFunction(见 multimapagg/MultimapAggregationFunction.java)同样将键去重建立在TypedSet之上以控制重复键的内存膨胀。0.155 的优化目标正是减少这些路径中重复持有或过早物化的中间结构。
语法与功能调整
INCLUDING / EXCLUDING / PROPERTIES 改为非保留关键字
INCLUDING、EXCLUDING与PROPERTIES三个词在 0.155 中被调整为非保留关键字(non-reserved keywords)。这意味着它们不再占用标识符的合法命名空间,用户可以将它们用作表名、列名等标识符(例如SELECT * FROM "properties"或直接SELECT including FROM t),同时仍可作为表/分区属性语法(如SHOW CREATE TABLE输出的WITH (...)属性块,以及 Hive 表属性中的TBLPROPERTIES语义)中的关键字使用。这一调整降低了关键字对用户命名的干扰。
移除基于采样表的近似查询实验特性
0.155移除了基于采样表(sampled tables)计算近似查询的实验性功能。该特性曾是 Presto 早期用于快速近似分析的方案,通过系统化地对表进行采样来估计聚合结果。移除后,近似分析能力让位于approx_*系列精确近似函数(如approx_distinct、approx_percentile等)。
值得注意的是,采样相关能力并未整体消失:现代版本以key_based_sampling会话属性族的形式保留了采样能力——key_based_sampling_enabled、key_based_sampling_percentage、key_based_sampling_function(见 SystemSessionProperties.java),并存在KeyBasedSampler计划优化器(见 KeyBasedSampler.java)以及EvaluateZeroSample等采样相关计划规则。可以看出 0.155 移除的是"整表采样近似"这一实验路径,而采样语义本身在后续版本中演化为受控的关键字采样方案。
准确统计创建 page source 的时间
0.155 开始在指标中准确记录创建 page source(数据页源)所花费的时间。page source 是 Presto 在物理执行计划中为表扫描等数据来源建立的页生产者,其创建耗时此前被笼统归入其他阶段。修复后,运维人员可以在查询统计信息中区分"数据源构建"与"实际读取"两个阶段的耗时,更精确地定位扫描性能瓶颈。
降低协调节点 CPU 占用的若干优化
0.155 包含多项面向 coordinator 的 CPU 优化,包括减少不必要的计划克隆、优化任务状态轮询与心跳处理的常数开销等。此类优化通常不可从单条 SQL 观察到,但在集群规模较大、查询并发较高时对协调节点的吞吐与延迟有实际收益。
Hive Changes:Parquet、KMS 与 Avro
新 Parquet 读器修复 schema 演进
0.155 修复了新 Parquet 读器(new Parquet reader)在 **schema 演进(schema evolution)**场景下的支持问题。schema 演进指底层 Parquet 文件与当前表 schema 不一致(如新增列、列类型放宽)时仍能正确读取。修复前,新读器在处理演进后的 schema 时可能发生类型映射或列裁剪错误;修复后行为与旧读器对齐。当前仓库中该能力沉淀于 presto-parquet 模块,其中包含 170 个主代码文件,ParquetReader与其测试套件覆盖了复杂 schema 与演进场景。
Hadoop KMS 的 NoClassDefFoundError 修复
使用 Hadoop KMS(Key Management Server,用于透明加密的密钥管理服务)时,0.155 之前可能出现NoClassDefFoundError。这通常是因为 KMS 相关类(如org.apache.hadoop.crypto.key.kms.*)在特定类加载环境下未被正确初始化或依赖缺失。修复通过调整 Hive 连接器对 Hadoop 安全组件的类加载顺序/依赖声明解决,使启用 KMS 加密的表可正常读写。
新增 Avro 文件格式支持
0.155 为 Hive 连接器新增 Avro 文件格式支持,这是本版本 Hive 侧最重要的功能增量。在 HiveStorageFormat.java 中,AVRO枚举将 Hive 侧的AvroSerDe、AvroContainerInputFormat与AvroContainerOutputFormat组合起来,并声明了 64MB 的默认压缩缓冲阈值:
AVRO( AvroSerDe.class.getName(), AvroContainerInputFormat.class.getName(), AvroContainerOutputFormat.class.getName(), new DataSize(64, Unit.MEGABYTE)),这意味着用户可以直接创建 Avro 格式的 Hive 表:
CREATE TABLE events_avro ( event_id BIGINT, event_type VARCHAR, payload VARCHAR ) WITH ( format = 'AVRO' );与 Avro 配套的 schema 管理同样贯通:HiveMetadata中定义了AVRO_SCHEMA_URL表属性,并规定只有当存储格式为 AVRO 时才能指定该属性,否则抛出INVALID_TABLE_PROPERTY错误(见 HiveMetadata.java)。读取已存在 Avro 表时,schema URL 会从 metastore 表参数(AVRO_SCHEMA_URL_KEY)中取出并还原为表属性(同文件 HiveMetadata.java)。因此,使用外部工具(如 Hive 或 Spark)创建的 Avro 表,只要其 schema 注册在 Hive Metastore 中,Presto 即可直接查询。
DWRF 字典编码流始终产出字典块
0.155 还保证DWRF(Facebook 优化的 ORC 变体)字典编码流始终产出字典块(dictionary blocks)。DWRF 对字典编码的流在读取时若直接解出原始值而非保持字典形式,会失去下游(如谓词下推、向量化计算)利用字典的能力。0.155 修复后,读取 DWRF 字典流时统一保持 dictionary block 形态,从而保住压缩与计算效率。
SPI Changes:移除 legacy connector API
0.155 的 SPI 变更只有一条,但影响面最大:彻底移除 legacy connector API。
在此之前,Presto SPI 同时保留了一套"传统"连接器接口与一套新式接口(围绕ConnectorMetadata、ConnectorSplitManager、ConnectorPageSourceProvider等按职责拆分的设计),legacy API 用于兼容早期插件。0.155 将 legacy 接口删除,意味着:
- 第三方连接器插件必须实现新式 SPI 接口,否则无法加载;
- 插件开发者升级到 0.155 时,需要将连接器代码迁移到以
ConnectorMetadata/ConnectorSplitManager/ConnectorPageSourceProvider/ConnectorRecordSetProvider等为核心的 SPI 模型。
当前仓库的 presto-spi 模块(519 个主代码文件)即为这一新式 SPI 契约的完整体现,所有内置连接器(Hive、Iceberg、Kafka、Pinot 等)均遵循该契约实现。
升级与验证建议
针对要升级到 0.155 及之后的部署,结合本版本变更给出如下实操建议:
- 回归重复 grouping sets 查询:对线上
GROUPING SETS/ROLLUP/CUBE查询做结果比对,确认聚合正确性修复未引入行为变化(该修复只影响重复集合的查询,正常查询不受影响)。 - 关注内存指标上涨:升级后简单聚合、Top N、DISTINCT 查询的 reported memory 可能上升,这是记账修正的结果,需按新口径调整内存告警阈值。
- 避免保留关键字冲突:由于
INCLUDING、EXCLUDING、PROPERTIES变为非保留关键字,此前因关键字冲突而加引号的标识符可以简化;反之无需任何改动。 - Hive 侧验证:对新 Parquet 读器下的 schema 演进表执行扫描测试;若使用 KMS 加密,验证读写正常;如需使用 Avro 格式,可通过
format = 'AVRO'建表并配合avro_schema_url属性指定 schema。 - 插件兼容性检查:任何第三方连接器需确认已迁移到新式 SPI,legacy 接口在 0.155 已不可用。
延伸阅读
- 版本发布说明原文:release-0.155.rst
- 后续版本发布说明目录:presto-docs/src/main/sphinx/release
- 新式 SPI 契约:presto-spi
- Parquet 读器实现:presto-parquet
- Hive 存储格式枚举:HiveStorageFormat.java
- Avro 相关表属性处理:HiveMetadata.java
- 大数据
- 数据库
- 后端
【免费下载链接】presto
The official home of the Presto distributed SQL query engine for big data
相关推荐
Presto Release 0.172 解析:查询正确性修复、Lambda 规划增强与聚合内存优化
Presto Release 0.172 解析:查询正确性修复、Lambda 规划增强与聚合内存优化 Presto 是面向大数据场景的分布式 SQL 查询引擎,
大数据数据库后端Presto Release 0.164 深度解读:查询正确性修复、EXPLAIN VALIDATE 模式与 Hive 桶表调度优化
Presto Release 0.164 深度解读:查询正确性修复、EXPLAIN VALIDATE 模式与 Hive 桶表调度优化 导读 本文围绕 Prest
大数据数据库后端Presto Release 0.219 技术解析:查询正确性修复、Hive 分桶读取增强与 Verifier 验证框架重构
Presto Release 0.219 技术解析:查询正确性修复、Hive 分桶读取增强与 Verifier 验证框架重构 导读 :本文以官方发布说明 rel
大数据数据库后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考