Page 269 - 《软件学报》2026年第3期
P. 269
1232 软件学报 2026 年第 37 卷第 3 期
p 1 (a) AND p 2 (b)
OR p 3(c): Item_func_ge(c,3) OR p 3 (c)
e 1 e 2
T
p 1(a): Item_func_lt(a,1) %a <get_row_values(A)>
AND >=
%a
F
< > c 3 %b <get_row_values(B)> %c <get_row_values(C)>
%b %c
p 2(b): Item_func_gt(b,2)
T
a 1 b 2
F
图 3 谓词表达式代码生成示例
3.3.3 混合编译
MySQL 支持多种数据类型和功能, 其中许多类型 (如字符串、日期和复杂几何类型) 在表达式求值时引入了
复杂的处理逻辑. 例如, 字符串类型支持不同的字符集和排序规则, 需要根据标准进行正确的处理; JSON 或 GIS
类型的求值则依赖动态链接库实现空间计算或数据解析, 这类操作在解释执行时通过 MySQL 内置函数逐行处理,
但在 JIT 编译中面临显著挑战. 以 JSON 字段的提取操作为例, 其底层需调用 JSON_EXTRACT 函数解析字符串
并构建内存中的树状结构, 这一过程涉及动态内存分配和递归遍历, 难以直接映射到静态的 LLVM IR. 因此, 考虑
到支持所有类型、运算符和函数的实现复杂性, 并且这些功能在本研究中并不会带来实质性提升, MySQLJ 将重
点支持常见的数据类型和运算符 (如 INT、CHAR、VARCHAR、DATE 和 DECIMAL) 以及基本的逻辑运算符
(AND、OR、NOT) 和比较运算符 (>=、<=、BETWEEN、!=、= 和 LIKE). 这些类型和运算符覆盖了大多数实际
业务场景, 能够有效验证 JIT 编译技术对 MySQL 查询性能的提升效果.
对于未支持的数据类型或运算符, MySQLJ 采用了混合编译的方式. 具体来说, 对于 Item 树中不支持的数据
类型, 我们不会对其进行完整的编译, 而是通过外部调用机制来处理这些不支持的类型. 这意味着, 当编译生成的
代码在动态执行时遇到这些节点时, 它会回调虚函数 (如 val_int()) 来完成表达式求值. 这种处理方式虽然没有完
全消除该节点的函数调用开销, 但可以确保其他支持的节点能够通过编译执行, 从而避免使用解释执行. 通过这种
混合编译方法, 即便在遇到不支持的类型时, 系统依然能够正常编译执行, 尽管存在少数未支持的类型需要回退到
虚函数调用, 但整体查询性能依然能得到显著改善.
3.4 引擎层过滤模块
在 MySQL 中, 不同的存储引擎采用不同的存储和访问方式. 以 InnoDB 引擎为例, 其采用了聚簇索引存储格
式, 数据行存储在 B+ 树的叶子节点中. 当进行全表扫描时, 整条记录需要从磁盘读取并转换为 MySQL 格式, 这一
过程涉及大量的格式转换和数据复制开销. 为了减少这一开销, 存储引擎层的过滤模块通过下推的字段编号, 仅转
换查询所需的字段数据, 避免了对整个数据行的转换. 接下来, 模块通过下推的机器码对字段数据进行表达式求
值, 只有符合条件的记录会被进一步处理并转换为 MySQL 格式.
经过筛选后的数据会加入缓冲池中, 而不符合条件的记录则会被过滤掉. 当下推谓词的选择率较低时, 这种处
理方式能够显著减少无效数据的加载, 降低内存和 I/O 开销. 最终, 缓冲池中的数据会被传输到服务层做进一步处
理. 通过在存储引擎层提前过滤数据, 不仅避免了不必要的数据加载, 还有效减少了存储引擎与服务层之间的数据
传输 I/O 开销.
4 实验评价
本节主要对采用 JIT 编译的 MySQLJ 与原生 MySQL 进行对比实验. 首先, 利用 sysbench 工具测试单表查询
在不同数据量、数据类型以及是否包含主键这 3 种场景下开启 JIT 编译系统前后的数据库性能表现. 随后, 测试

