PostgreSQL JIT 详细讲解

 更新时间:2026年05月14日 08:26:14   作者:undefinedType  
PostgreSQL的JIT是 PostgreSQL 11 引入的一个高级性能优化特性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

PostgreSQL JIT 详细讲解

PostgreSQL 的 JIT(Just-In-Time Compilation)是 PostgreSQL 11 引入的一个高级性能优化特性。

很多人会误以为:

“开启 JIT = SQL 自动变快”

实际上并不是。

在真实生产环境中:

  • 有些系统开启后性能提升明显
  • 有些系统开启后 CPU 飙升、RT 变差
  • 很多 Rails / API 系统最后会选择关闭 JIT

所以理解 JIT 的核心,不是“怎么开启”,而是:

它到底优化什么、适用于什么场景、为什么会拖慢系统。

一、JIT 是什么?

JIT 全称:

Just-In-Time Compilation(即时编译)

本质上:

PostgreSQL 会把 SQL 执行中的部分逻辑,动态编译成机器码执行。

传统 PostgreSQL 的执行方式

默认情况下,PostgreSQL 是:

SQL
→ Parser(解析)
→ Planner(生成执行计划)
→ Executor(执行器)
→ Interpreter(逐行解释执行)

也就是说:

SQL 中的表达式:

price * tax_rate > 100

会被 PostgreSQL 一行一行解释执行。

每处理一行:

  • 读取字段
  • 做运算
  • 做判断
  • 返回结果

这种方式灵活,但 CPU 开销较高。

二、JIT 的核心原理

JIT 会把这些“重复执行的表达式逻辑”:

price * tax_rate > 100

编译成:CPU 可以直接执行的机器码

从而:

  • 减少解释器开销
  • 减少函数调用
  • 提升 CPU 执行效率

三、JIT 解决什么问题?

JIT 主要解决的是:

“CPU 计算开销过高”的问题

不是 IO 问题。

四、JIT 优化的核心场景

JIT 主要优化:

类型示例
表达式计算CASE WHEN、数学运算
JSONB 解析-> / ->>
WHERE 复杂过滤多层条件
聚合计算SUM / COUNT / GROUP BY
大量行处理Seq Scan / Bitmap Scan
CPU 密集型 SQL报表统计

五、JIT 不优化什么?

JIT:

❌ 不优化磁盘 IO
❌ 不优化索引
❌ 不优化网络
❌ 不优化锁等待
❌ 不优化慢 JOIN 算法

六、JIT 的真正优化目标

JIT 优化的是:

Executor 阶段中的“表达式执行成本”

即:每处理一行数据时的 CPU 成本

七、JIT 工作流程

PostgreSQL JIT 基于 LLVM。

工作流程:

SQL
→ Planner
→ Executor
→ LLVM IR
→ Machine Code
→ CPU 执行

八、JIT 的几个阶段

EXPLAIN ANALYZE 中你会看到:

JIT:
  Functions: 10
  Options: Inlining true, Optimization true
  Timing:
    Generation 3.2 ms
    Inlining 20 ms
    Optimization 35 ms
    Emission 10 ms

1. Generation

生成 LLVM IR。

2. Inlining

函数内联。

减少函数调用成本。

3. Optimization

LLVM 做代码优化。

4. Emission

生成机器码。

九、为什么 JIT 有时候反而更慢?

JIT 的本质:编译成本 + 执行收益

如果:编译时间 > 节省时间

那么:

JIT 就会拖慢 SQL

十、典型错误场景

❌ 小 SQL

SELECT * FROM users WHERE id = 1;

问题:

  • SQL 执行可能只要 1ms
  • JIT 编译可能花 5~20ms

结果:

总耗时变大

❌ 高频 API SQL

Rails / GraphQL 系统非常常见:

SELECT * FROM tasks WHERE project_id = ? LIMIT 20;

特点:

  • 高频
  • 短 SQL
  • 延迟敏感

这种场景:

JIT 几乎一定不划算

❌ 高并发系统

JIT 会:

  • 增加 CPU
  • 增加 LLVM 编译压力
  • 增加 latency spike

十一、哪些场景适合 JIT?

✔ 报表系统(OLAP)

例如:

SELECT
    user_id,
    SUM(price * tax_rate)
FROM orders
GROUP BY user_id;

特点:

  • 扫描大量数据
  • 计算复杂
  • SQL 执行时间长

✔ 大 JSONB 查询

SELECT *
FROM logs
WHERE metadata->>'type' = 'error';

✔ 数据分析类 SQL

  • 大聚合
  • 大过滤
  • CPU-heavy

十二、哪些场景不适合?

❌ OLTP

例如:

  • Rails
  • 微服务
  • GraphQL
  • API Server

特点:

  • 查询短
  • QPS 高
  • latency 敏感

❌ 索引查询为主

WHERE id = ?

这种本来就很快。

❌ 高并发在线业务

JIT 容易导致:

  • CPU 波动
  • RT 抖动
  • p99 上升

十三、如何查看 JIT 是否生效?

查看是否开启

SHOW jit;

查看 JIT 参数

SHOW jit_above_cost;
SHOW jit_inline_above_cost;
SHOW jit_optimize_above_cost;

十四、核心参数详解

1. jit

是否开启。

SET jit = on;

2. jit_above_cost(最重要)

表示:

查询成本超过多少才启用 JIT

默认通常较高。

避免小 SQL 被误伤。

3. jit_inline_above_cost

是否启用 inline。

4. jit_optimize_above_cost

是否启用 LLVM 优化。

十五、如何分析 JIT 问题?

最重要的方法:

1. EXPLAIN ANALYZE

EXPLAIN (ANALYZE, BUFFERS, JIT)
SELECT ...

你会看到:

JIT:
  Functions: 8
  Timing:
    Generation 4ms
    Optimization 30ms

2. pg_stat_statements 统计 JIT 开销(核心排查 SQL)

下面这条 SQL 可以用于:

  • 找出正在使用 JIT 的 SQL
  • 分析 JIT 平均耗时
  • 判断 JIT 是否值得
  • 排查哪些 SQL 被 JIT “误伤”
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;

十六、如何解读这条排查 SQL?

avg_exec_ms

total_exec_time / calls

平均执行时间。

avg_jit_ms(核心)

(
 jit_generation_time +
 jit_inlining_time +
 jit_optimization_time +
 jit_emission_time
) / calls

表示:

每次 SQL 平均花多少时间在 JIT 编译上

jit_percent(最关键指标)

jit_time / total_exec_time

表示:

SQL 总时间中,有多少比例浪费在 JIT 上

十七、如何判断当前 SQL 不适合 JIT?

🚨 情况 1:jit_percent > 20%

说明:

很多时间都浪费在 LLVM 编译,而不是 SQL 执行。

这是最典型的:

  • API SQL
  • Rails SQL
  • GraphQL SQL

问题。

🚨 情况 2:avg_jit_ms 很高

例如:

指标
avg_exec_ms20ms
avg_jit_ms8ms

说明:

40% 时间花在 JIT 上。

通常不划算。

🚨 情况 3:calls 非常高

例如:

callsavg_exec_ms
1000005ms

这种高频 SQL:

几乎一定不适合 JIT

因为:

编译成本根本无法摊销。

🚨 情况 4:IO 很低但 CPU 很高

例如:

avg_disk_read 很低
avg_buffer_hit 很低
但 avg_exec_ms 很高

说明:

问题不是 IO。

而是:

CPU 计算 + JIT 开销

十八、生产环境最佳实践

OLTP 系统(Rails / API)

通常建议:

jit = off

原因:

  • latency 更稳定
  • CPU 更低
  • p99 更好

OLAP / 报表系统

建议:

jit = on

因为:

  • SQL 很长
  • CPU-heavy
  • 编译成本可摊销

十九、生产上最推荐的策略

不是:

全局开

也不是:

全局关

而是:

推荐方案

默认关闭

jit = off

报表 SQL 单独开启

SET LOCAL jit = on;

或提高触发门槛

jit_above_cost = 100000

避免短 SQL 被 JIT。

二十、总结一句话

PostgreSQL JIT 是一个“用编译换执行速度”的 CPU 优化器,只适合“大量数据 + 复杂计算”的 SQL,不适合高频短查询 OLTP 系统。

二十一、你当前场景的判断(结合你之前的问题)

你之前提到:

  • 慢 SQL
  • Rails
  • GraphQL
  • API
  • CPU 压力
  • 怀疑 JIT 导致慢查询

这种场景里:

关闭 JIT 是非常常见且合理的优化方向。

因为:

你的系统更像:

OLTP / API 型系统

而不是:

OLAP / 报表型系统

所以:

jit = off

很可能会:

  • 降低 CPU
  • 提升 RT 稳定性
  • 降低 p99
  • 减少 latency spike

到此这篇关于PostgreSQL JIT 详细讲解的文章就介绍到这了,更多相关PostgreSQL JIT内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • phpPgAdmin 常见错误和问题的解决办法

    phpPgAdmin 常见错误和问题的解决办法

    这篇文章主要介绍了phpPgAdmin 常见错误和问题的解决办法,如安装错误、登陆错误、转储功能、其它错误和问题等,需要的朋友可以参考下
    2014-03-03
  • 使用navicat连接postgresql报错问题图文解决办法

    使用navicat连接postgresql报错问题图文解决办法

    我们在日常开发中有时候需要用navicate连接postgresql数据库,有时候会连接不上数据库,下面这篇文章主要给大家介绍了关于使用navicat连接postgresql报错问题图文解决办法,需要的朋友可以参考下
    2023-11-11
  • Linux系统安装PostgreSQL数据库及配置的详细过程

    Linux系统安装PostgreSQL数据库及配置的详细过程

    这篇文章主要给大家介绍了关于Linux系统安装PostgreSQL数据库及配置的详细过程,PgSQL(全称PostgreSQL)是一个功能强大的开源对象-关系型数据库系统,结合了许多安全存储和扩展最复杂数据工作负载的功能,需要的朋友可以参考下
    2023-12-12
  • 关于向PostgreSQL数据库插入Date类型数据报错问题解决方案

    关于向PostgreSQL数据库插入Date类型数据报错问题解决方案

    本文给大家介绍在将数据库从Oracle改为PostgreSQL时遇到的日期类型插入错误,通过使用PostgreSQL的特定语法和更改动态SQL语句解决了问题,本文给大家介绍的非常详细,需要的朋友参考下吧
    2024-12-12
  • PostgreSQL的扩展 dblink及安装使用方法

    PostgreSQL的扩展 dblink及安装使用方法

    dblink 是 PostgreSQL 的一个核心扩展,允许在当前数据库中访问其他 PostgreSQL 数据库的数据,实现跨数据库查询功能,本文给大家介绍PostgreSQL的扩展 dblink的相关知识,感兴趣的朋友一起看看吧
    2025-07-07
  • postgresql IvorySQL新增命令及相关配置参数详解

    postgresql IvorySQL新增命令及相关配置参数详解

    这篇文章主要为大家介绍了postgresql IvorySQL新增命令及相关配置参数详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 自定义函数实现单词排序并运用于PostgreSQL(实现代码)

    自定义函数实现单词排序并运用于PostgreSQL(实现代码)

    这篇文章主要介绍了自定义函数实现单词排序并运用于PostgreSQL,本文给大家分享实现代码,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • postgreSQL如何设置数据库执行超时时间

    postgreSQL如何设置数据库执行超时时间

    本文我们将深入探讨PostgreSQL数据库中的一个关键设置SET statement_timeout,这个设置对于管理数据库性能和优化查询执行时间非常重要,让我们一起来了解它的工作原理以及如何有效地使用它
    2024-01-01
  • PostgreSQL归档配置及自动清理归档日志的操作

    PostgreSQL归档配置及自动清理归档日志的操作

    这篇文章主要介绍了PostgreSQL归档配置及自动清理归档日志的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • PostgresSql 多表关联删除语句的操作

    PostgresSql 多表关联删除语句的操作

    这篇文章主要介绍了PostgresSql 多表关联删除语句的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01

最新评论