- 大数据
- 数据库
- 后端
【免费下载链接】presto
The official home of the Presto distributed SQL query engine for big data
导读
Presto 0.259 是 PrestoDB(GitHub 加速计划 / pre / presto)发布的一个重要版本,围绕 SQL 函数、错误诊断、JDBC 连接能力与资源组治理四个方面进行了增强:新增了 Weibull 分布的 CDF 与逆 CDF 数学函数;默认开启内存超限错误的详细诊断信息;为 JDBC 驱动新增连接属性读取接口并支持 JDBC 过滤条件下推;资源组新增了单查询级(per-query)的 CPU 时间、内存与执行时间限制。本文以官方发布说明 release-0.259.rst 为主线,结合仓库源码与测试用例,逐项解析这些新能力的语法、配置方法、实现原理与使用场景。
⚠️ 版本警示:本版本在 JDBC Connector 上存在一个已知回归(regression),升级或部署前请充分评估与测试。
一、General Changes:查询引擎的通用改进
1.1 修复 EXPLAIN 与 LIKE 谓词组合时的 ClassCastException
本版本修复了一个偶发的ClassCastException:当查询中包含LIKE谓词并且执行EXPLAIN时,某些场景下会抛出类型转换异常。修复后,EXPLAIN配合LIKE谓词的查询可以正常生成执行计划,这对日常使用EXPLAIN分析查询性能的开发与运维人员是一个直接的稳定性改进。
1.2 新增 Weibull 分布 CDF 与逆 CDF 函数
本版本在 SQL 数学函数库中新增了两个与 Weibull 分布相关的函数,用于可靠性工程、寿命数据分析、故障时间建模等场景:
weibull_cdf(a, b, value)→ double:计算参数为a、b的 Weibull 分布的累积分布函数值P(N <= value)。inverse_weibull_cdf(a, b, p)→ double:计算给定累积概率p对应的 Weibull 分布分位数。
两个函数均要求a、b为正的 DOUBLE 值;inverse_weibull_cdf的概率参数p必须落在[0, 1]区间内。函数形式化定义与参数约束参见数学函数文档 math.rst。
源码实现原理
这两个函数定义于 MathFunctions.java,内部委托给 Apache Commons Math 的WeibullDistribution实现:
@Description("Weibull cdf given the a, b parameters and value") @ScalarFunction @SqlType(StandardTypes.DOUBLE) public static double weibullCdf( @SqlType(StandardTypes.DOUBLE) double a, @SqlType(StandardTypes.DOUBLE) double b, @SqlType(StandardTypes.DOUBLE) double value) { checkCondition(a > 0, INVALID_FUNCTION_ARGUMENT, "weibullCdf Function: a must be greater than 0"); checkCondition(b > 0, INVALID_FUNCTION_ARGUMENT, "weibullCdf Function: b must be greater than 0"); WeibullDistribution distribution = new WeibullDistribution(null, a, b, WeibullDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY); return distribution.cumulativeProbability(value); }从源码可以看出,参数校验在 SQL 函数入口处显式完成(a > 0、b > 0),非法参数会以INVALID_FUNCTION_ARGUMENT错误抛出,而不是静默返回异常数值;分布计算使用WeibullDistribution.DEFAULT_INVERSE_ABSOLUTE_ACCURACY作为逆 CDF 求解精度控制。
用法示例与参数约束
-- 计算 Weibull(1.0, 0.6) 分布在 3.0 处的 CDF 值 SELECT weibull_cdf(1.0, 0.6, 3.0); -- ≈ 0.99 -- 计算 Weibull(1.0, 0.6) 分布的 0.91 分位数 SELECT inverse_weibull_cdf(1.0, 0.6, 0.91); -- ≈ 1.44 -- 非法参数会直接报错 SELECT weibull_cdf(0, 3, 0.5); -- ERROR: a must be greater than 0 SELECT inverse_weibull_cdf(3, 5, 1.1); -- ERROR: p must be in the interval [0, 1]上述示例与错误信息均来自测试用例 TestMathFunctions.java 中的testWeibullCdf与testInverseWeibullCdf,可用于验证安装版本的行为是否符合预期。这些函数与既有的normal_cdf、poisson_cdf、t_cdf、inverse_normal_cdf等概率函数构成了一套完整的分布分析工具集,方便在 SQL 中直接完成统计建模而不必导出数据。
1.3 默认启用 EXCEEDED_LOCAL_MEMORY_LIMIT 详细错误信息
当查询超过单节点本地内存限制(EXCEEDED_LOCAL_MEMORY_LIMIT)时,Presto 0.259 默认会在错误信息中附带额外的算子内存分配详情,帮助定位内存超限的具体环节。若希望恢复精简的错误信息,可在config.properties中显式关闭:
memory.verbose-exceeded-memory-limit-errors-enabled=false配置项在源码中的定义与默认值
该配置项定义于 NodeMemoryConfig.java:
public boolean isVerboseExceededMemoryLimitErrorsEnabled() { return verboseExceededMemoryLimitErrorsEnabled; } @Config("memory.verbose-exceeded-memory-limit-errors-enabled") @ConfigDescription("When enabled the error message for exceeded memory limit errors will contain additional operator memory allocation details") public NodeMemoryConfig setVerboseExceededMemoryLimitErrorsEnabled(boolean verboseExceededMemoryLimitErrorsEnabled) { this.verboseExceededMemoryLimitErrorsEnabled = verboseExceededMemoryLimitErrorsEnabled; return this; }注意:verboseExceededMemoryLimitErrorsEnabled的字段初始值即为true(NodeMemoryConfig.java),即“默认开启”;配置测试 TestNodeMemoryConfig.java 也验证了将该项设为false的行为。
详细错误信息包含什么
错误信息的构造逻辑位于 QueryContext.java:当开关开启时,错误消息会在基础信息之上追加:
- Top Consumers:按内存占用排序的前 3 个内存消费者及其占用字节数(
succinctBytes格式化); - Details:各 Task 的内存预留摘要(
TaskMemoryReservationSummary),按预留内存从大到小排序,仅包含预留大于 0 的 Task,最多 3 个。
if (verboseExceededMemoryLimitErrorsEnabled) { List<TaskMemoryReservationSummary> memoryReservationSummaries = getTaskMemoryReservationSummaries(); message += ", Details: " + memoryReservationSummaryJsonCodec.toJson(memoryReservationSummaries); }这意味着开启后,当查询触发本地内存超限时,错误信息会直接告诉你“哪些算子/任务吃掉了最多的内存”,对排查 OOM 类问题有直接的指导价值。生产环境若担心错误信息过长影响日志可读性,可通过上述配置项关闭。
二、JDBC Driver Changes:连接属性读取
2.1 新增getConnectionProperties方法
Presto 0.259 为 JDBC 驱动中的PrestoConnection新增了getConnectionProperties()方法(对应 PR #16329),用于在连接建立之后检索连接属性。该方法在 PrestoConnection.java 中实现:
public Properties getConnectionProperties() { Properties properties = new Properties(); for (Map.Entry<Object, Object> entry : connectionProperties.entrySet()) { properties.setProperty((String) entry.getKey(), (String) entry.getValue()); } return properties; }从实现看,它返回的是connectionProperties的一个拷贝,而不是内部引用,因此调用方修改返回的Properties不会污染驱动内部状态,这是良好的 API 设计。
使用场景
当应用通过 JDBC URL 传入大量连接参数(如user、password、extraCredentials、sessionProperties等)时,连接建立后可以通过该方法回读实际生效的属性,用于调试、审计或动态决策。例如:
try (PrestoConnection connection = (PrestoConnection) DriverManager.getConnection(jdbcUrl)) { Properties props = connection.getConnectionProperties(); String extraCredentials = props.getProperty("extraCredentials"); // ... }对应的测试 TestJdbcConnection.java 验证了通过extraCredentials=test.token.foo:bar;test.token.abc:xyz建立连接后,getConnectionProperties()返回的Properties非空且能正确取回extraCredentials属性:
@Test public void testConnectionProperties() throws SQLException { String extra = "extraCredentials=test.token.foo:bar;test.token.abc:xyz"; try (PrestoConnection connection = createConnection(extra).unwrap(PrestoConnection.class)) { Properties connectionProperties = connection.getConnectionProperties(); assertTrue(connectionProperties.size() > 0); assertNotNull(connectionProperties.getProperty("extraCredentials")); } }注意该方法定义在PrestoConnection上(而非 JDBC 标准接口java.sql.Connection),因此调用时需要先unwrap(PrestoConnection.class)或直接使用PrestoConnection类型引用。
三、JDBC Connector Changes:过滤条件部分下推
本版本为 JDBC Connector 增加了**过滤条件的部分下推(partial pushdown of JDBC filters)**能力。此前 JDBC Connector 对过滤条件下推的支持较为有限,复杂过滤条件可能整体无法下推;部分下推意味着查询中的部分过滤条件(如某些简单谓词)可以被下推到远端数据库执行,而无法下推的剩余条件则由 Presto 本地完成过滤。
这一能力在 JDBC 数据源(MySQL、PostgreSQL、ClickHouse、Oracle、SQL Server、Redshift、SingleStore 等基于presto-base-jdbc构建的连接器)上可以降低从远端数据库拉取的数据量,从而减少网络传输与本地计算开销。从源码结构看,该能力位于 presto-base-jdbc 模块,各 JDBC 系连接器(如 presto-mysql、presto-postgresql)均依赖此基座。实际下推效果取决于底层数据库对 SQL 表达式的支持能力。
四、Resource Groups Changes:资源组级查询限制
4.1 新能力概览
Presto 0.259 允许在资源组(Resource Group)级别为其中的每条查询设置三类上限:
- 执行时间限制(executionTimeLimit):单条查询最长允许执行的时间,例如
1h; - 总内存限制(totalMemoryLimit):单条查询最多允许消耗的分布式内存,例如
1GB; - CPU 时间限制(cpuTimeLimit):单条查询最多允许使用的 CPU 时间,例如
1h。
当查询超过其中任一限制时,该查询会被终止(killed)。该功能的具体配置语法参见资源组文档 resource-groups.rst。需要特别注意的是:这些 per-query 限制不会被父组继承,每个资源组需要独立配置。
4.2 JSON 配置示例
在资源组的 JSON 配置文件中,通过新增的perQueryLimits字段配置(完整示例可参考测试配置 resource_groups_config.json):
{ "rootGroups": [ { "name": "global", "softMemoryLimit": "1MB", "hardConcurrencyLimit": 100, "maxQueued": 1000, "schedulingPolicy": "weighted", "jmxExport": true, "perQueryLimits": { "executionTimeLimit": "1h", "totalMemoryLimit": "1MB", "cpuTimeLimit": "1h" }, "subGroups": [ { "name": "sub", "softMemoryLimit": "2MB", "hardConcurrencyLimit": 3, "maxQueued": 4, "schedulingWeight": 5 } ] } ], "selectors": [ { "group": "global" } ], "cpuQuotaPeriod": "1h" }executionTimeLimit、totalMemoryLimit、cpuTimeLimit三个字段均为可选;不配置的维度表示不设限。
4.3 SPI 层新增ResourceGroupQueryLimits
为了实现上述能力,Presto 0.259 在 SPI 中新增了不可变类ResourceGroupQueryLimits,并为其对应的ResourceGroups接口补充了 getter/setter。该类定义于 ResourceGroupQueryLimits.java:
public final class ResourceGroupQueryLimits { private final Optional<Duration> executionTimeLimit; private final Optional<DataSize> totalMemoryLimit; private final Optional<Duration> cpuTimeLimit; public static final ResourceGroupQueryLimits NO_LIMITS = new ResourceGroupQueryLimits(Optional.empty(), Optional.empty(), Optional.empty()); ... }设计要点:
- 三个字段均为
Optional,未配置的维度为Optional.empty(); - 提供静态常量
NO_LIMITS表示“无任何限制”,InternalResourceGroup默认使用该值(InternalResourceGroup.java); - 类带有
@JsonCreator/@JsonProperty注解,支持 JSON 序列化与反序列化,这正是配置文件与 SPI 对象之间的桥梁; - 该类为
final且字段不可变,保证并发场景下的安全共享。
4.4 运行时如何生效
在运行时,InternalResourceGroup通过setPerQueryLimits(...)接收配置,并在查询启动时将限制传递给查询执行层(InternalResourceGroup.java):
query.setResourceGroupQueryLimits(perQueryLimits);查询执行层(SqlQueryExecution、QueryTracker、ClusterMemoryManager等,见 presto-main-base 与 presto-main/src/main/java/com/facebook/presto/memory/ClusterMemoryManager.java)随后根据这些限制对查询的执行时间、CPU 时间与总内存进行监控,超限即终止查询。这意味着资源组管理员可以针对不同业务组(如 ETL 批处理、临时查询)设定差异化的单查询资源上限,防止单个失控查询拖垮整个组。
五、版本升级与部署注意事项
- JDBC Connector 回归:本版本在 JDBC Connector 上存在已知回归,使用 JDBC 数据源(尤其是跨多个 JDBC 连接器的混合负载)的生产集群在升级前应重点回归测试过滤下推与查询下推场景;
- 新配置项:
memory.verbose-exceeded-memory-limit-errors-enabled默认值为true(对应 NodeMemoryConfig.java),如不需要详细内存错误信息,可在升级后显式关闭以保持错误输出精简; - 资源组配置格式:若使用资源组功能,需确认配置文件格式与
perQueryLimits字段兼容;该字段为可选,旧配置文件不包含该字段时行为不变; - 新函数可用性:
weibull_cdf与inverse_weibull_cdf属于核心数学函数库,升级后所有查询引擎节点均可直接使用,无需额外安装插件。
参考资源
- 版本发布说明:release-0.259.rst
- 数学函数文档:math.rst
- 资源组管理文档:resource-groups.rst
- 函数实现:MathFunctions.java
- 函数测试:TestMathFunctions.java
- 内存配置:NodeMemoryConfig.java、QueryContext.java
- JDBC 驱动实现:PrestoConnection.java、TestJdbcConnection.java
- 资源组 SPI:ResourceGroupQueryLimits.java、InternalResourceGroup.java
- 大数据
- 数据库
- 后端
【免费下载链接】presto
The official home of the Presto distributed SQL query engine for big data
相关推荐
Presto 0.179 版本发布全解析:新函数、文件型全局安全与资源组查询时限
Presto 0.179 版本发布全解析:新函数、文件型全局安全与资源组查询时限 导读 本文以 Presto(Trino 前身)官方发布的 Release 0.
大数据数据库后端Presto 0.240 版本发布详解:窗口函数溢写、SQL 函数内联与查询扫描上限控制
Presto 0.240 版本发布详解:窗口函数溢写、SQL 函数内联与查询扫描上限控制 本篇技术指南以 Presto 官方发行说明 release 0.240
大数据数据库后端Presto 0.230 版本发布详解:函数编译修复、新数组函数与 Hive/Raptor 存储增强
Presto 0.230 版本发布详解:函数编译修复、新数组函数与 Hive/Raptor 存储增强 导读 Presto 0.230 是 Presto 分布式
大数据数据库后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考