JIT 是 Just-In-Time Compilation,即“即时编译”。意思是:程序运行到某段代码时,才把原本解释执行的逻辑编译成 CPU 可以直接执行的本机机器码。PostgreSQL 文档给的典型例子是:不用一个通用表达式解释器去判断 WHERE a.col = 3,而是为这个具体条件生成专门函数,让 CPU 直接执行。(PostgreSQL)
数据库 JIT 是什么
数据库里的 JIT 通常指:在 SQL 查询执行时,把查询计划中的某些表达式、过滤条件、投影、聚合、表结构访问等,动态生成并编译成更专用的机器码或 JVM 字节码/代码。
普通数据库执行大致是:
SQL → 解析 → 优化器生成执行计划 → 执行器解释执行
带 JIT 的执行可能变成:
SQL → 执行计划 → 为部分计划/表达式生成专用代码 → 编译 → 执行机器码
例如:
SELECT sum(price * quantity)
FROM orders
WHERE status = 'PAID' AND amount > 100;
JIT 可能会把 status = 'PAID'、amount > 100、price * quantity 这类表达式编译成更直接的代码,而不是每一行都通过通用表达式解释器判断。
作用是什么
核心作用是:减少解释执行开销,提高 CPU 密集型查询的执行速度。
主要收益有这些:
- 减少函数调用和解释器分发开销
通用执行器需要不断判断“这个表达式是什么类型、调用哪个函数、下一步做什么”。JIT 可以把这些逻辑提前固化成专用代码。 - 表达式内联和优化
PostgreSQL 的 JIT 可以加速表达式求值和 tuple deforming,也就是把磁盘/行格式中的 tuple 转换成内存表示;还可以做小函数内联和 LLVM 优化。(PostgreSQL) - 适合长时间、CPU-bound、分析型查询
JIT 本身有编译成本,所以短查询可能得不偿失。PostgreSQL 文档明确说,JIT 主要对长时间运行的 CPU 密集型查询有利,常见是分析型查询;短查询的编译开销可能超过节省的执行时间。(PostgreSQL) - 对重复查询形状更有价值
SingleStore 这类系统会把相同 query shape 的查询编译/缓存起来,后续相同形状的请求可以复用已生成的计划和代码。(docs.singlestore.com)
但 JIT 也有代价:编译要耗时、占内存、实现复杂,而且不是所有 SQL 算子都适合 JIT。比如 QuestDB 文档就列出其 JIT SQL compiler 对 CPU 架构、AVX2、函数类型、过滤条件等有支持限制。(QuestDB)
哪些数据库/SQL 引擎使用了 JIT 或类似代码生成
| 数据库 / 引擎 | JIT / 代码生成情况 |
|---|---|
| PostgreSQL | 内置 LLVM JIT 支持,可加速表达式求值、tuple deforming、内联和优化;是否启用由查询成本阈值控制。(PostgreSQL) |
| ClickHouse | 官方有 “JIT in ClickHouse” 介绍,使用 LLVM 基础设施做 JIT,用于提升查询执行中的部分计算性能。(ClickHouse) |
| SingleStore / MemSQL | 使用 code generation,将查询形状转换为系统内部 IR 并生成高效机器码;后续相同形状查询可复用编译结果。(docs.singlestore.com) |
| QuestDB | 有 SQL JIT compiler,主要针对包含 WHERE 过滤条件的查询;文档说明 6.3 之后默认开启。(QuestDB) |
| Apache Spark SQL | 不一定叫数据库 JIT,但 Spark SQL 使用 code generation 来加速查询;Whole-stage codegen 会生成 Java 代码,再由 JVM JIT 优化执行。Spark 官方也说明 Spark SQL 包含 cost-based optimizer、columnar storage 和 code generation。(spark.apache.org) |
| SQL Server | 不是通用 SQL 查询 JIT,但 In-Memory OLTP 支持 memory-optimized tables 和 natively compiled stored procedures,生成 DLL,提高访问和执行效率。(Microsoft Learn) |
| DuckDB | 典型情况下不走 SQL JIT,而是选择向量化解释执行。DuckDB 论文说明它因可移植性和 LLVM 等大型依赖问题,选择 vectorized interpreted execution 而不是 SQL JIT。 |
一句话总结:数据库 JIT 是把“通用执行器解释 SQL”的一部分,变成“为当前查询专门生成并执行机器码”。它适合复杂、长时间、CPU 计算重的分析查询;对短小 OLTP 查询不一定有利。
Bytecode和JIT的关系
Bytecode(字节码) 和 JIT(即时编译) 不是同一层东西。
一句话:
Bytecode 是一种中间代码格式;JIT 是一种把代码在运行时编译成机器码的技术。
1. Bytecode 是什么
Bytecode 是介于源代码和机器码之间的中间表示。
例如 Java:
int x = a + b;
编译后不是直接变成 x86 / ARM 机器码,而是先变成 JVM 能理解的 bytecode:
iload_1
iload_2
iadd
istore_3
Bytecode 本身通常不能直接被 CPU 执行,需要由虚拟机解释执行,或者进一步编译。
常见例子:
| 系统 | Bytecode |
|---|---|
| Java | JVM bytecode |
| Python | CPython bytecode |
| .NET | CIL / MSIL |
| SQLite | VDBE bytecode |
| PostgreSQL | 表达式执行中也会有类似中间表示,但不一定叫 bytecode |
2. JIT 是什么
JIT 是 Just-In-Time Compilation,即时编译。
它的作用是:程序运行时,把某些代码编译成 CPU 可以直接执行的机器码。
比如 JVM 执行 Java bytecode 时,开始可能解释执行:
JVM bytecode → JVM 解释器执行
如果发现某段代码很热、执行很多次,JIT 会把它编译成机器码:
JVM bytecode → JIT 编译 → x86 / ARM 机器码
之后 CPU 就可以直接跑这段机器码,速度通常更快。
3. 二者核心区别
| 对比项 | Bytecode | JIT |
|---|---|---|
| 本质 | 中间代码格式 | 运行时编译技术 |
| 是“什么” | 一种代码表示 | 一种执行优化方式 |
| 什么时候产生 | 通常在编译前期或解释器准备阶段 | 程序运行时 |
| 谁执行 | 虚拟机解释器,或 JIT 编译后由 CPU 执行 | JIT 编译器负责编译,CPU 执行结果机器码 |
| 是否一定更快 | 不一定 | 热代码通常更快,但有编译开销 |
| 典型例子 | Java bytecode、Python bytecode、SQLite VDBE bytecode | JVM JIT、V8 JIT、PostgreSQL LLVM JIT |
4. 它们的关系
Bytecode 和 JIT 经常一起出现,但不是必须绑定。
常见路径是:
源代码↓
Bytecode↓
解释执行
或者:
源代码↓
Bytecode↓
JIT 编译↓
机器码↓
CPU 执行
所以可以理解为:
Bytecode 是 JIT 的输入之一;JIT 的输出通常是机器码。
但 JIT 不一定必须从 bytecode 开始,它也可以从 AST、IR、查询计划、LLVM IR 等中间表示开始。
5. 放到数据库里怎么理解
以数据库执行 SQL 为例:
Bytecode 型数据库执行
比如 SQLite 会把 SQL 编译成自己的 VDBE bytecode:
SELECT name FROM users WHERE age > 18;
大致变成:
OpenRead
Rewind
Column
Gt
ResultRow
Next
Halt
然后由 SQLite 的虚拟机一条一条解释执行这些 bytecode。
JIT 型数据库执行
PostgreSQL、ClickHouse、SingleStore 等系统可能会把查询中的表达式、过滤条件、聚合逻辑等编译成本机机器码:
WHERE age > 18
可能被生成成专门的机器码函数,而不是每一行都解释执行表达式。
6. 一个类比
可以这样理解:
Bytecode 像菜谱的标准步骤。
它不是食物本身,也不是厨师直接的肌肉动作,而是一套中间指令。
解释器像厨师每次照着菜谱一步步做。
JIT 像厨师发现这道菜要做一万遍,于是专门训练出一套最快动作流程。
以后再做同一道菜,就不用每次慢慢查菜谱了。
总结
Bytecode 是“代码长什么样”;JIT 是“代码怎么被加速执行”。
更准确地说:
Bytecode = 中间表示
Interpreter = 解释执行 bytecode
JIT = 运行时把 bytecode/IR 编译成机器码
Machine code = CPU 真正执行的代码
向量化执行(Vectorized Execution) 和 JIT 的关系
向量化执行(Vectorized Execution) 和 JIT 都是数据库执行引擎的加速技术,但它们解决问题的方式不同。
一句话:
向量化执行是“批量解释执行”;JIT 是“生成专用机器码执行”。
1. 普通解释执行的问题
传统 Volcano / iterator 执行模型通常是一行一行处理:
for each row:取一行判断 WHERE 条件计算表达式输出结果
问题是每处理一行都可能产生大量函数调用、分支判断、虚函数调用、类型判断,CPU 利用率不高。
2. 向量化执行是什么
向量化执行不是一行一行处理,而是一批一批处理。
例如一次处理 1024 行:
for each batch of 1024 rows:批量读取 age 列批量判断 age > 18批量计算表达式批量输出结果
它的核心思想是:
把数据库操作作用在一列或一批数据上,而不是单行数据上。
例如:
SELECT price * quantity
FROM orders
WHERE amount > 100;
向量化执行会更像这样:
amount[0..1023] > 100
price[0..1023] * quantity[0..1023]
这样有几个好处:
| 优点 | 解释 |
|---|---|
| 减少函数调用开销 | 一次处理一批数据,而不是每行调用一次 |
| 更适合 CPU cache | 批量、连续访问列数据 |
| 更适合 SIMD | CPU 可以一条指令处理多个值 |
| 分支预测更友好 | 减少逐行判断带来的分支开销 |
| 实现相对简单 | 比 JIT 更容易控制和调试 |
常见采用向量化执行的系统包括 DuckDB、ClickHouse、Vectorwise、SQL Server Batch Mode、Snowflake/Velox 类执行框架 等。
3. JIT 是什么
JIT 是在运行时为当前查询生成专门代码。
例如这个条件:
WHERE amount > 100 AND status = 'PAID'
普通解释执行可能每一行都调用通用表达式解释器。
JIT 会生成类似这样的专用函数:
bool filter(row) {return row.amount > 100 && row.status == "PAID";
}
然后编译成本机机器码执行。
它的核心思想是:
不是优化“批量处理方式”,而是减少解释器开销,生成当前查询专用代码。
4. 二者的关系
它们不是互斥关系,而是两种不同层次的优化。
可以这样理解:
解释执行:
一行一行,用通用解释器执行向量化执行:
一批一批,用通用向量算子执行JIT 执行:
为当前查询生成专用机器码执行向量化 + JIT:
一批一批处理,同时某些表达式/算子由 JIT 生成专用代码
5. 核心区别
| 对比项 | 向量化执行 | JIT |
|---|---|---|
| 优化对象 | 数据处理粒度 | 代码执行方式 |
| 核心思想 | 一批数据一起处理 | 为查询生成专用代码 |
| 输入单位 | batch / vector / column chunk | 查询计划、表达式、IR、bytecode |
| 输出 | 批量执行结果 | 机器码或可执行函数 |
| 是否需要编译 | 通常不需要 | 需要运行时编译 |
| 启动开销 | 较低 | 有编译开销 |
| 更适合 | OLAP、扫描、聚合、列式处理 | 长查询、复杂表达式、CPU 密集型计算 |
| 短查询表现 | 通常也不错 | 可能因编译成本不划算 |
| 实现复杂度 | 中到高 | 高 |
6. 用一个例子对比
SQL:
SELECT sum(price * quantity)
FROM orders
WHERE status = 'PAID';
行式解释执行
读一行
解释 status = 'PAID'
解释 price * quantity
累加 sum
读下一行
特点:简单,但每行开销大。
向量化执行
读一批 status
批量生成过滤 mask
读一批 price、quantity
批量计算 price * quantity
批量累加 sum
特点:减少逐行开销,适合列式和 OLAP。
JIT 执行
根据这个 SQL 生成专门的过滤和计算函数
编译成机器码
执行机器码
特点:表达式执行很快,但前面要付编译成本。
向量化 + JIT
每次处理一批数据
但过滤和表达式计算由 JIT 生成的专用代码完成
这是两者结合的形式。
7. 谁更好?
没有绝对更好,取决于场景。
向量化执行通常更稳。
它没有明显的编译开销,适合大量扫描、过滤、聚合、连接等分析型任务。
JIT 在复杂表达式、长查询、重复执行的 query shape 上可能更强。
但短查询可能还没跑多久,JIT 编译成本就已经超过收益了。
所以很多现代数据库会选择:
短查询:解释执行或向量化执行
中大型 OLAP 查询:向量化执行
复杂 CPU-bound 查询:JIT
高性能系统:向量化 + JIT / codegen
8. 一个直观类比
向量化执行 像工厂流水线:
一次处理一批零件,效率来自批量化和缓存友好。
JIT 像为某个订单定制一台专用机器:
机器造出来之后跑得很快,但造机器本身有成本。
结论
向量化执行和 JIT 是并列但可组合的数据库执行优化技术。
更准确地说:
向量化执行:减少“逐行处理”的开销
JIT:减少“通用解释器”的开销
它们解决的问题不同:
向量化关注:数据怎么喂给 CPU
JIT 关注:CPU 执行什么代码
现代高性能数据库常常会在二者之间做权衡,甚至同时使用。
向量化执行与JIT的取舍
可以把它们看成两条优化路线:
向量化执行:一次处理一批数据,靠 batch、列式内存、cache/SIMD 提升吞吐。
JIT / Codegen:为当前查询生成专用代码,减少解释器、虚函数、分支和类型分派开销。
一、明确同时使用向量化和 JIT / Codegen 的数据库
| 系统 | 是否同时使用 | 说明 |
|---|---|---|
| ClickHouse | 是 | ClickHouse 是典型列式、向量化执行系统;其官方文章说明 ClickHouse 也有 JIT,可编译表达式、聚合函数、ORDER BY 比较器等,并且会用阈值和 LRU cache 避免重复编译成本。(ClickHouse) |
| QuestDB | 是 | QuestDB 文档直接写明 Query Engine 包含 JIT compiler 和 vectorized execution engine;其 JIT 面向 full scan / partition scan 中的过滤表达式,可生成机器码,并可使用 SIMD/vector 指令。(QuestDB) |
| SingleStore | 是,偏 codegen + columnar batch | SingleStore 文档说明它使用 code generation,把查询形状编译为高效机器码;VLDB 论文也说明 SingleStore 使用 LLVM full-query code generation,列存扫描会产出 column-oriented batch,列存可利用 SIMD。(SingleStore 文档) |
| Apache Spark SQL | 广义上是,但不完全等同于 ClickHouse 这类 native vectorized engine | Spark SQL 官方说它包含 cost-based optimizer、columnar storage 和 code generation;但标准 Spark SQL 的 Whole-stage codegen 更多是 JVM 代码生成路线,而 Databricks Photon 论文把 Spark SQL 归为 code-generated design,并说明 Photon 选择了 vectorized-interpreted 路线。(Apache Spark) |
其中最典型的“向量化 + JIT 混合”例子,我会优先举 ClickHouse、QuestDB、SingleStore。
二、明确在向量化和 JIT 之间做取舍的数据库 / 引擎
| 系统 | 取舍方向 | 为什么 |
|---|---|---|
| DuckDB | 选择向量化解释执行,放弃 SQL JIT | DuckDB 论文明确说它使用 vectorized interpreted execution engine,并且选择这种方式而不是 SQL JIT,原因包括可移植性,以及不想依赖 LLVM 这类大型编译器库。(DuckDB) |
| Databricks Photon | 选择 native C++ 向量化解释执行,而不是 code generation | Photon 论文明确写到:它选择 vectorized-interpreted model in lieu of code generation;原因包括运行时自适应、工程上更容易开发/调试/线上运维。论文也承认某些复杂条件表达式下 code generation 可能更快。(EECS Berkeley) |
| Snowflake | 公开论文中偏向 columnar + vectorized + push-based 执行 | Snowflake 论文把其执行引擎描述为 columnar、vectorized、push-based;数据以几千行为一批、列式格式流水线处理。它不是公开文献里常见的 HyPer/Impala 那种“主打全查询 JIT/codegen”的代表。 |
| Apache Doris | 偏向向量化 | Doris 文档说每个查询都运行在 vectorized engine 上,Block 最多 4096 行;这类设计主要押注 batch/column/SIMD,而不是把通用 SQL JIT 作为核心路线。(Doris) |
| PostgreSQL | 偏传统 iterator + 可选 LLVM JIT | PostgreSQL 官方文档说明其 JIT 主要加速表达式求值和 tuple deforming;它不是 ClickHouse/DuckDB 那种以向量化 OLAP 执行为核心的系统。(PostgreSQL) |
| Impala / HyPer / Spark SQL | 偏 code generation / compilation 路线 | Photon 论文把 Spark SQL、HyPer、Apache Impala 归到 code-generated design 一侧,而把 MonetDB/X100 这类归到 interpreted vectorized design 一侧。(EECS Berkeley) |
三、为什么有些系统两者都用,有些只选一种
向量化执行的优势是稳定、启动成本低、容易利用列式内存和 SIMD,适合 OLAP 扫描、过滤、聚合、join。缺点是表达式逻辑很复杂时,仍然会有一些解释/分派开销。
JIT 的优势是能把当前查询的表达式、聚合、比较器、过滤条件融合成专用代码,长查询、复杂表达式、重复 query shape 会受益。缺点是有编译开销、工程复杂、调试困难、内存占用和缓存管理问题。
所以不同数据库的选择大概是:
DuckDB / Photon / Snowflake / Doris更偏向:向量化执行PostgreSQL更偏向:传统 iterator + 可选 JITImpala / HyPer / Spark SQL更偏向:code generation / JIT 路线ClickHouse / QuestDB / SingleStore更像:向量化 + JIT/codegen 混合
四、一个判断标准
看到一个数据库时,可以这样判断:
如果它说 batch、chunk、block、vector、columnar batch、SIMD,通常是向量化路线。
如果它说 LLVM、native code、machine code、code generation、query compilation、compiled expression,通常是 JIT/codegen 路线。
如果两个都出现,而且是在执行引擎层面结合,比如 “columnar batches + compiled expressions/filters/aggregates”,那就是混合路线。ClickHouse、QuestDB、SingleStore 都属于这个方向。
Tiered JIT 是什么
Tiered JIT 可以翻译成 分层即时编译 / 多级 JIT。
它的核心思想是:
不要一上来就花很多时间生成最高质量机器码,而是先用便宜方式跑起来;如果代码真的变热,再逐级编译成更快、更优化的机器码。
1. Tiered JIT 是什么
典型执行路径是:
Level 0:解释执行↓ 代码执行次数变多,收集 profile
Level 1:快速 JIT / baseline JIT,编译快,但优化少↓ 继续变热,profile 更充分
Level 2:优化 JIT,编译慢,但生成代码质量更高
以 HotSpot JVM 为例,官方文档说它有 client compiler 和 server compiler:client compiler 编译快、适合启动阶段;server compiler 编译更慢、占用更多内存,但生成更优化的机器码。Tiered compilation 就是把解释器、快速编译器和优化编译器组合起来。(Oracle 文档)
Red Hat 对 HotSpot 的描述更直观:Java 代码先在解释器中执行;方法变 warm 后进入 quick compiler;如果继续变 hot,再进入 optimizing compiler;执行可以先切到低层编译代码,等更快的高层代码准备好后再切过去。(Red Hat Developer)
2. 和普通 JIT 的区别
普通 JIT 可以是:
解释执行一段时间 → 直接编译成一种机器码
Tiered JIT 是:
解释执行→ 快速编译,先获得中等性能→ 后台继续收集 profile→ 对真正热点代码做重优化编译→ 必要时 deopt 回退
所以它优化的是 “启动延迟、编译成本、峰值性能”之间的平衡。
| 对比 | 普通 JIT | Tiered JIT |
|---|---|---|
| 编译层级 | 通常单层 | 多层 |
| 启动速度 | 可能较慢,尤其直接重优化 | 更快,先 baseline |
| 峰值性能 | 取决于编译器 | 热代码可进入优化层 |
| 是否需要 profile | 可以有 | 非常依赖 profile |
| 实现复杂度 | 较低 | 更高 |
| 典型系统 | 简单 VM、部分数据库 JIT | JVM、V8、.NET 等运行时 |
.NET 官方文档也把 tiered compilation 描述为两层:第一层快速生成代码或加载预编译代码,第二层在后台生成优化代码。(Microsoft Learn)
3. 数据库有没有用 Tiered JIT?
答案要分两类。
4. 第一类:数据库自己实现“SQL 层面的 Tiered JIT”
生产数据库里比较少见。
很多数据库有 JIT,但不是典型 tiered JIT。例如 PostgreSQL 有 LLVM JIT,但它主要是在计划阶段根据成本决定是否 JIT、是否 inline、是否做 expensive optimization;这些决策发生在 plan time,而不是运行中先 baseline、再优化、再动态切换。(PostgreSQL)
PostgreSQL 的 JIT 主要加速表达式求值和 tuple deforming,也就是为 WHERE、投影、聚合表达式、tuple 解包生成专用代码。(PostgreSQL) 这更像 cost-gated JIT,不是经典的 tiered JIT。
QuestDB 也有 SQL JIT,它会对 full scan / partition scan 中的过滤表达式生成机器码,并且可能使用 SIMD/vector 指令;文档没有把它描述为多层 tiered JIT。(QuestDB)
所以:
PostgreSQL / QuestDB / ClickHouse 这类:
有 JIT 或 codegen
但通常不是经典 HotSpot/V8 那种 tiered JIT
5. 第二类:运行在 JVM 上的 SQL 引擎,间接使用 Tiered JIT
这类可以说 用了 tiered JIT,但主要是在 JVM 层,不一定是数据库自己实现的 SQL tiered JIT。
典型例子:
Spark SQL
Spark SQL 有 whole-stage code generation,会把多个物理算子融合成一个 Java 函数,并用 Janino 在运行时编译 Java 源码为 Java class。(japila-books)
之后这些生成出来的 Java 方法会被 JVM 执行,而 HotSpot JVM 默认支持 tiered compilation。Oracle 文档说明 tiered compilation 是 server VM 的默认模式。(Oracle 文档)
所以 Spark SQL 的链路大致是:
SQL plan→ Spark whole-stage codegen 生成 Java 代码→ Janino 编译成 JVM bytecode→ JVM 解释 / C1 / C2 tiered JIT→ 机器码
这里的 tiered JIT 是 JVM 提供的,不是 Spark 自己写了一个 SQL tiered JIT。
Trino / Presto 类 JVM SQL 引擎
Trino 是 JVM 上的 SQL 引擎,生产环境中会遇到 JVM JIT recompilation、code cache 等问题;Trino 项目讨论中也提到它通过 JVM JIT 把 JVM bytecode 转成本机 CPU 指令。(trino.io)
所以 Trino / Presto 这类系统也可以说:
查询执行代码 / 表达式代码→ JVM bytecode 或 Java 方法→ HotSpot tiered JIT
但同样要注意:这是 依赖 JVM 的 tiered JIT,不是数据库引擎自己管理 SQL 查询的多层 JIT。
Calcite 系生态
Apache Calcite 文档说明它使用 Janino 生成 Java 代码。(Apache Calcite) 因此,基于 Calcite 并实际在 JVM 中执行生成代码的系统,也可能间接受益于 JVM tiered JIT。
6. 研究型系统里有更接近“数据库 Tiered JIT”的设计
学术界有一些更接近数据库版 tiered JIT / adaptive compilation 的设计。
比如 Adaptive Execution of Compiled Queries 这篇基于 HyPer 思路的论文,提出了一个框架:先用专门为数据库查询设计的 bytecode interpreter 执行,同时动态跟踪查询进度,并在解释执行和编译执行之间切换,以兼顾短查询低延迟和长查询高吞吐。
这非常接近数据库里的 tiered JIT 思路:
短查询:先解释执行,避免编译成本
长查询:后台编译完成后切换到机器码
图数据库方向也有 adaptive query compilation 研究:引擎先解释执行,同时检索或生成编译代码,用来隐藏编译或代码加载开销。(Springer Nature Link)
7. 总结
Tiered JIT = 分阶段 JIT:先快编译,后重优化。
放到数据库里可以这样理解:
不是 tiered JIT:
SQL → 计划 → 要么解释执行,要么一次性 JIT 成机器码tiered JIT:
SQL → 计划→ 先解释 / bytecode / baseline code 执行→ 查询或表达式变热→ 后台生成更优化机器码→ 动态切换过去
目前结论是:
| 类型 | 例子 | 是否算 Tiered JIT |
|---|---|---|
| JVM SQL 引擎 | Spark SQL、Trino / Presto、Calcite 系 | 间接是,依赖 JVM tiered JIT |
| PostgreSQL LLVM JIT | PostgreSQL | 不是典型 tiered JIT,更像成本阈值控制的 JIT |
| 原生 SQL JIT | QuestDB、ClickHouse 等 | 有 JIT/codegen,但通常不叫 tiered JIT |
| 研究型 adaptive query compilation | HyPer 相关论文、图数据库 adaptive compilation | 很接近数据库版 tiered JIT |
一句话:真正成熟、广泛使用的 tiered JIT 主要在 JVM/.NET/V8 这类语言运行时里;数据库系统更多是“成本控制的 JIT”或“依赖 JVM 的 tiered JIT”。
