Apache Cloudberry 向量化实践(三)重塑表达式构建路径:Gandiva 优化实战

在向量化执行系统中,表达式构建是不可或缺的基础环节。无论是 SQL 中的投影、筛选,还是分区、聚合、排序,最终都需转化为底层执行引擎能识别和执行的表达式树。而在 Apache Cloudberry 向量化执行框架中,这一过程由 Gandiva 表达式引擎负责完成。
随着数据规模与查询复杂度的提升,我们逐渐意识到,表达式构建本身正成为影响执行性能的关键路径之一。特别是在高并发、多表达式拼接的场景下,构建过程的性能瓶颈愈加突出。本文将结合实际优化案例,分享我们如何识别问题、设计优化方案,并用火焰图验证成效。

为何选 Gandiva?JIT + Arrow 的组合拳
Gandiva 是 Apache Arrow 项目中的子模块,它基于 LLVM 构建 JIT 编译能力,专为高性能、批量化的列式计算而设计。我们选择 Gandiva 作为表达式引擎的主要原因有三点:

  1. 向量化执行友好:Gandiva 表达式以 Arrow RecordBatch 为输入/输出单位,与 Cloudberry 的内存格式完全兼容,避免额外序列化/反序列化开销。
  2. JIT 编译能力强:Gandiva 支持将表达式编译为本地机器码,执行效率显著优于解释执行。
  3. 表达式树抽象清晰:其表达式结构基于语法树(AST),便于分析、合并、转换、优化。
    但“强大”背后也隐藏着一个问题:表达式构建过程并非“零成本”,尤其在表达式数量和深度快速增长时,构建开销成为了不容忽视的负担。

原始构建路径的问题:节点重复 & 树结构过深
在未优化前,我们采用“逐表达式构建”的方式——每处理一条 SQL 表达式,就从头创建一棵新的表达式树。这种策略在简单查询下运行良好,但在复杂嵌套查询、窗口函数、联表计算等场景下暴露出以下问题:

  1. 公共子表达式重复构建:同一表达式片段(如 lower(colA))在不同上下文中多次出现时,每次都重新生成节点,造成冗余。
  2. 表达式树结构深且复杂:表达式链条变长时,嵌套层级加深,构建耗时近似呈线性增长。
  3. Hash 逻辑不稳定:相同表达式结构,由于构建路径差异导致节点 hash 不一致,影响缓存和优化判断。
    我们对典型查询的表达式构建过程进行了耗时统计,结果显示:
  • 在包含 20+ 表达式的复杂查询中,表达式构建耗时占整体查询时间的 10%~15%;
  • 其中约 40% 的表达式为可复用的子表达式,但未被有效识别与复用;
  • 构建阶段的所有开销几乎全部集中在 on-CPU 路径上,火焰图显示 CreateExpressionNode、ToArrowNode 等函数在 CPU 调用栈中占比极高,成为构建瓶颈的主要耗时点。
    这些现象表明:表达式构建过程不仅费时,而且浪费资源。

优化策略:公共子表达式识别 + 哈希原子化
我们采用两项优化手段来重构表达式构建路径:

  1. 公共子表达式识别(CSE)
    引入表达式 DAG 结构,在构建过程中为每个子表达式生成唯一 key(基于语义签名),并放入全局表达式缓存池。后续若再次请求相同表达式,直接复用已有子树。
  • 优点:减少冗余节点构建,降低构建深度;
  • 技术点:等价表达式归一化(如 a + b vs b + a)、表达式 hash 去重。
  1. 哈希表达式原子化
    将每一个表达式节点封装为具有确定性 hash 的原子单元,避免因构建路径差异导致 hash 冲突。统一采用 结构 hash + 类型信息 + 参数签名 的组合哈希策略,确保缓存命中率提升。
    优化后,我们实现了表达式构建路径的“结构性去重”:从构建“树”转为拼装“块”,如搭积木般复用构建单元,降低系统负担。

优化效果对比:结构简化 & 构建耗时下降
通过对比优化前后在复杂 SQL 下的表达式构建过程,我们观察到以下显著变化:
在这里插入图片描述

不仅节点数量明显下降,构建时间也随之降低了50%以上,特别是在复合查询中表现尤为明显。

火焰图验证:构建路径 on-CPU 时间显著下降
我们进一步通过 perf 工具配合火焰图对比优化前后的 CPU 使用情况,焦点集中在表达式构建阶段。
优化前的火焰图中,Gandiva::TreeExprBuilder::MakeExpression() 及其内部调用占据主火焰图的 30% 高度,显著吞噬 on‑CPU 资源。
优化后,火焰图中该函数堆栈深度显著缩减,仅占主图不到 10%,并可见更多时间释放给后续执行逻辑,如 Eval、Filter、Project 等。
这说明:表达式构建从 CPU 消耗的“主角”,退回到了其应有的“配角”角色。

表达式构建常被认为是“编译期行为”,但在现代向量化系统中,它的性能表现直接影响执行链路的起跑速度。
通过本次优化,我们验证了如下几点:

  • 表达式构建本身具有显著的优化空间;
  • 结构性去重 比单纯加快构建速度更有效;
  • 可观测性工具(如火焰图) 是评估优化效果的关键利器。
    这也为后续优化其他执行环节(如重分布、调度、缓存)提供了经验模板:先观测,再定位,再结构重构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88452.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows删除文件或者拔出U盘显示正在使用/占用解决办法

1、复制文件地址2、打开任务管理器,选择左侧【性能】3、打开资源监视器4、选择资源监视器中的CPU5、粘贴你复制的占用文件地址6、除了explore.exe以外,其他的关联的句柄都选中,然后右键结束

自由学习记录(68)

🧠 blender为什么不用 M 或 T? 键位含义为什么没选MMove?其实被用作「Move to Collection」等功能不符合历史定义,而且功能太多了TTransform? 但 transform 是一个总称(含移动、旋转、缩放)T 被…

ReactNative【实战系列教程】我的小红书 8 -- 我(含左侧弹窗菜单,右下角图标等)

最终效果点左上角菜单按钮,弹出左侧菜单后代码实现app/(tabs)/mine.tsx import icon_add from "/assets/icons/icon_add.png"; import mine_bg from "/assets/images/mine_bg.png"; import Heart from "/components/Heart"; import a…

C++性能优化实战:从理论到落地的五大核心策略

在当今这个对计算效率要求极高的时代,C作为系统级编程语言的王者,其性能优化能力依然是无可替代的核心竞争力。本文将分享我在大型分布式系统开发中积累的C性能优化实战经验,这些经验帮助我们将关键组件的吞吐量提升了300%,延迟降…

字节 Seed 团队联合清华大学智能产业研究院开源 MemAgent: 基于多轮对话强化学习记忆代理的长文本大语言模型重构

🔥 最新动态!!! [2025/07] 我们提供了快速启动脚本,让使用MemAgent变得超级简单,详情请见下方"快速入门"部分。[2025/06] 我们发布了RL-MemAgent-14B和RL-MemAgent-7B模型,在350万token上下文任务中实现了近乎无损的性…

【unitrix】 4.20 类型级二进制数减法实现解析(sub.rs)

一、源码 这段代码实现了一个用于统计二进制补码整数位数的系统,支持多种自定义数值类型(Z0、P1、N1、B0、B1)。 use core::mem::size_of; use crate::number::{Z0, P1, N1, B0, B1, Var};/// 统计二进制位数的 trait pub trait BitLength {f…

手把手教你安全删除Anaconda虚拟环境(避坑指南)

文章目录一、删除前必看清单(超级重要)二、三种删除方法对比(建议收藏)方法1:官方推荐命令(最安全)方法2:暴力删除大法(快速但需谨慎)方法3:核弹级…

Effective Modern C++ 条款7:区分使用 `()` 和 `{}` 创建对象

在 C11 及以后的版本中,初始化对象的方式变得更加灵活,但也带来了选择上的困惑。() 和 {} 是两种常见的初始化语法,它们在语义、行为和适用场景上有显著差异。本文将通过具体示例,深入解析这两种初始化方式的区别,并探…

Java基础-String常用的方法

String常用的三种构造方法 public static void main(String[] args) {//1.使用常量字符串构造String s1 "1.Hello world";System.out.println(s1);//2.使用new关键字构造String s2 new String("2.Hello world");System.out.println(s2);//3。使用字符数组…

数学建模:多目标规划:ε约束法、 理想点法

一、ε约束法定义ε约束法通过将部分目标函数转化为约束条件,保留一个主要目标进行优化。1、选择一个主要目标 fk​(x) 进行优化。2、其他目标 fi​(x) 转化为约束 fi​(x)≤εi​,其中 εi​ 是决策者设定的容许阈值。​​原理​​​​目标选择​​&…

linux kernel struct regmap_config结构详解

在 Linux 内核中,struct regmap_config 是 ​Regmap 子系统的核心配置结构体,用于定义如何与底层硬件寄存器进行交互。Regmap(Register Map)子系统通过抽象不同总线(如 I2C、SPI、MMIO 等)的寄存器访问细节…

【Python3教程】Python3高级篇之CGI编程

博主介绍:✌全网粉丝23W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

docker安装Consul笔记

安装过程 详细步骤如下: 首先拉取Consul的Docker镜像: docker pull hashicorp/consul:1.18.1创建Consul的配置文件和数据目录: mkdir -p /srv/docker/consul/data mkdir -p /srv/docker/consul/config在config目录下创建一个config.json配置文…

.net数据脱敏

.NET数据脱敏技术:保障数据安全的有效手段 在当今数字化时代,数据安全至关重要。尤其是涉及到用户的敏感信息,如密码、手机号码等,必须采取有效的措施进行保护。数据脱敏就是这样一种技术,它能够在不影响数据可用性的…

【openp2p】 学习2:源码阅读P2PNetwork和P2PTunnel

【openp2p】 学习1:P2PApp和优秀的go跨平台项目已经做了初步分析。阅读原版工程,感觉工程是一个暴露内网服务端口,让外部可以用的一个实现是一个完整的、跨平台的可商业化的应用。感谢作者需要学习作者的设计思路工程构建 F:\GolandProjects\openp2p\core\p2pnetwork.go通常…

网安学习NO.14

防火墙基础实验 传统防火墙配置实验拓扑图PC: ip 192.168.10.1 255.255.255.0 192.168.10.254 ip dns 114.114.114.114二层交换机 vl 10 ex int e0/0 sw mo ac sw ac vl 10 ex inr e0/1 sw tr en do sw mo tr三层交换机 vl 10 ex int g0/0 sw tr en do sw mo tr ex …

ESP32语音唤醒

两种唤醒方式AfeWakeWord与EspWakeWord对比 底层技术 AfeWakeWord:基于ESP-IDF的AFE框架(esp_afe_sr_iface_t),高性能模式(AFE_MODE_HIGH_PERF)EspWakeWord:基于WakeNet接口(esp_wn_…

借助 Wisdom SSH AI 助手,轻松安装 CentOS 8 LNMP 环境

打开Wisdom SSH软件,在AI对话区输入“在CentOS 8服务器安装LNMP环境”,AI助手会按以下步骤分析并执行安装: 安装Nginx 分析:CentOS 8默认软件源可能没有Nginx,所以要先启用Nginx官方软件源,然后才能安装Ngi…

WD0407 40V 7A 超级肖特基二极管,应用于开关汽车工业控制

WD0407 40V 7A 超级肖特基二极管说明​ 产品概述​ WD0407 是一款性能卓越的超级肖特基二极管,专为满足现代电子设备对高效、可靠电源管理的需求而设计。它采用先进的半导体制造工艺,在诸多关键性能指标上表现出色,能够为各类电路提供稳定、高…

卢比危机下的金融破局:科伦坡交易所技术升级作战图

🌏 今日南亚风暴眼 印度双重上市机制加速落地:印度国家证券国际交易所(NSE IX)与科伦坡证券交易所(CSE)达成技术对接协议,斯企可通过印度GIFT City吸引美元资本,交易时段覆盖全球22小…