91人参与 • 2026-05-14 • MsSqlserver
postgresql 的 jit(just-in-time compilation)是 postgresql 11 引入的一个高级性能优化特性。
很多人会误以为:
“开启 jit = sql 自动变快”
实际上并不是。
在真实生产环境中:
所以理解 jit 的核心,不是“怎么开启”,而是:
它到底优化什么、适用于什么场景、为什么会拖慢系统。
jit 全称:
just-in-time compilation(即时编译)
本质上:
postgresql 会把 sql 执行中的部分逻辑,动态编译成机器码执行。
默认情况下,postgresql 是:
sql → parser(解析) → planner(生成执行计划) → executor(执行器) → interpreter(逐行解释执行)
也就是说:
sql 中的表达式:
price * tax_rate > 100
会被 postgresql 一行一行解释执行。
每处理一行:
这种方式灵活,但 cpu 开销较高。
jit 会把这些“重复执行的表达式逻辑”:
price * tax_rate > 100
编译成:cpu 可以直接执行的机器码
从而:
jit 主要解决的是:
“cpu 计算开销过高”的问题
不是 io 问题。
jit 主要优化:
| 类型 | 示例 |
|---|---|
| 表达式计算 | case when、数学运算 |
| jsonb 解析 | -> / ->> |
| where 复杂过滤 | 多层条件 |
| 聚合计算 | sum / count / group by |
| 大量行处理 | seq scan / bitmap scan |
| cpu 密集型 sql | 报表统计 |
jit:
❌ 不优化磁盘 io
❌ 不优化索引
❌ 不优化网络
❌ 不优化锁等待
❌ 不优化慢 join 算法
jit 优化的是:
executor 阶段中的“表达式执行成本”
即:每处理一行数据时的 cpu 成本
postgresql jit 基于 llvm。
工作流程:
sql → planner → executor → llvm ir → machine code → cpu 执行
explain analyze 中你会看到:
jit:
functions: 10
options: inlining true, optimization true
timing:
generation 3.2 ms
inlining 20 ms
optimization 35 ms
emission 10 ms生成 llvm ir。
函数内联。
减少函数调用成本。
llvm 做代码优化。
生成机器码。
jit 的本质:编译成本 + 执行收益
如果:编译时间 > 节省时间
那么:
jit 就会拖慢 sql
select * from users where id = 1;
问题:
结果:
总耗时变大
rails / graphql 系统非常常见:
select * from tasks where project_id = ? limit 20;
特点:
这种场景:
jit 几乎一定不划算
jit 会:
例如:
select
user_id,
sum(price * tax_rate)
from orders
group by user_id;
特点:
select * from logs where metadata->>'type' = 'error';
例如:
特点:
where id = ?
这种本来就很快。
jit 容易导致:
show jit;
show jit_above_cost; show jit_inline_above_cost; show jit_optimize_above_cost;
是否开启。
set jit = on;
表示:
查询成本超过多少才启用 jit
默认通常较高。
避免小 sql 被误伤。
是否启用 inline。
是否启用 llvm 优化。
最重要的方法:
explain (analyze, buffers, jit) select ...
你会看到:
jit:
functions: 8
timing:
generation 4ms
optimization 30ms
下面这条 sql 可以用于:
select
query,
calls,
rows,
round((total_exec_time / calls)::numeric, 2) as avg_exec_ms,
round((total_plan_time / calls)::numeric, 2) as avg_plan_ms,
round(
(
(
jit_generation_time +
jit_inlining_time +
jit_optimization_time +
jit_emission_time
) / calls
)::numeric,
2
) as avg_jit_ms,
round(
(
(
jit_generation_time +
jit_inlining_time +
jit_optimization_time +
jit_emission_time
) / nullif(total_exec_time, 0) * 100
)::numeric,
2
) as jit_percent,
jit_functions,
round((shared_blks_hit::numeric / nullif(calls, 0)), 2) as avg_buffer_hit,
round((shared_blks_read::numeric / nullif(calls, 0)), 2) as avg_disk_read
from pg_stat_statements
where jit_functions > 0
order by jit_percent desc, avg_jit_ms desc
limit 20;
total_exec_time / calls
平均执行时间。
( jit_generation_time + jit_inlining_time + jit_optimization_time + jit_emission_time ) / calls
表示:
每次 sql 平均花多少时间在 jit 编译上
jit_time / total_exec_time
表示:
sql 总时间中,有多少比例浪费在 jit 上
说明:
很多时间都浪费在 llvm 编译,而不是 sql 执行。
这是最典型的:
问题。
例如:
| 指标 | 值 |
|---|---|
| avg_exec_ms | 20ms |
| avg_jit_ms | 8ms |
说明:
40% 时间花在 jit 上。
通常不划算。
例如:
| calls | avg_exec_ms |
|---|---|
| 100000 | 5ms |
这种高频 sql:
几乎一定不适合 jit
因为:
编译成本根本无法摊销。
例如:
avg_disk_read 很低 avg_buffer_hit 很低 但 avg_exec_ms 很高
说明:
问题不是 io。
而是:
cpu 计算 + jit 开销
通常建议:
jit = off
原因:
建议:
jit = on
因为:
不是:
全局开
也不是:
全局关
而是:
jit = off
set local jit = on;
jit_above_cost = 100000
避免短 sql 被 jit。
postgresql jit 是一个“用编译换执行速度”的 cpu 优化器,只适合“大量数据 + 复杂计算”的 sql,不适合高频短查询 oltp 系统。
你之前提到:
这种场景里:
关闭 jit 是非常常见且合理的优化方向。
因为:
你的系统更像:
oltp / api 型系统
而不是:
olap / 报表型系统
所以:
jit = off
很可能会:
到此这篇关于postgresql jit 详细讲解的文章就介绍到这了,更多相关postgresql jit内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论