PostgreSQL教程FG092-PG JIT编译:开启与性能调优
本文档风哥主要介绍PostgreSQL的JIT编译功能,包括开启方法、配置调优和性能测试。风哥教程参考PostgreSQL官方文档Server Administration内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
from oracle:www.itpux.com
Part01-基础概念与理论知识
1.1 PostgreSQL JIT编译的概念
PostgreSQL JIT(Just-In-Time)编译是指在运行时将SQL查询计划编译为机器码,以提高查询执行性能的技术。JIT编译可以加速复杂查询的执行,特别是包含表达式计算和函数调用的查询。更多视频教程www.fgedu.net.cn
- 运行时编译:在查询执行时动态编译查询计划
- 机器码执行:生成高效的机器码,提高执行速度
- 针对性优化:针对特定查询进行优化
- 可配置性:通过参数控制JIT编译的行为
1.2 PostgreSQL JIT编译的优势
PostgreSQL JIT编译的优势包括:
- 提高查询性能:特别是对于复杂查询和表达式计算
- 减少CPU使用:生成高效的机器码,减少CPU指令数
- 优化表达式计算:加速WHERE子句、聚合函数等表达式的计算
- 适应性优化:根据查询特点动态生成最优代码
- 可选择性启用:可以根据需要启用或禁用JIT编译
1.3 PostgreSQL JIT编译架构
PostgreSQL JIT编译的架构包括:
学习交流加群风哥QQ113257174
– 查询解析:解析SQL查询语句
– 查询优化:生成查询执行计划
– JIT编译:将执行计划编译为机器码
– 执行:执行编译后的机器码
– 结果返回:返回查询结果
# JIT编译流程
1. 优化器生成查询执行计划
2. 检查是否需要JIT编译
3. 如果需要,调用JIT编译器
4. JIT编译器将执行计划编译为机器码
5. 执行编译后的机器码
6. 返回查询结果
# JIT编译组件
– LLVM:JIT编译的底层框架
– PostgreSQL JIT接口:连接PostgreSQL和LLVM
– 代码生成器:生成机器码
– 优化器:优化生成的代码
Part02-生产环境规划与建议
2.1 PostgreSQL JIT编译规划
PostgreSQL JIT编译规划要点:
1. 分析系统硬件:了解服务器的CPU类型和性能
2. 分析工作负载:了解查询类型和复杂度
3. 确定JIT编译配置:设置合适的JIT编译参数
4. 测试JIT编译效果:在测试环境中测试JIT编译效果
5. 监控和调整:监控JIT编译的执行情况,根据需要调整参数
# JIT编译适用场景
– 复杂查询:包含大量表达式计算的查询
– 聚合查询:包含COUNT、SUM、AVG等聚合函数的查询
– 分析型查询:数据仓库和报表查询
– 表达式密集型查询:包含复杂WHERE子句的查询
# JIT编译不适用场景
– 简单查询:执行时间短的简单查询
– 高并发场景:大量并发连接的场景
– 内存不足的场景:JIT编译需要额外内存
– 磁盘IO密集型查询:受IO限制的查询
2.2 JIT编译配置建议
PostgreSQL JIT编译配置建议:
– jit:是否启用JIT编译,建议设置为on
– jit_buffer_size:JIT编译缓冲区大小,建议设置为16MB-64MB
– jit_above_cost:启用JIT编译的成本阈值,建议设置为100000
– jit_inline_above_cost:内联函数的成本阈值,建议设置为500000
– jit_optimize_above_cost:优化JIT编译的成本阈值,建议设置为500000
– jit_max_workers_per_gather:每个Gather节点的最大JIT工作者数,建议设置为4
# 配置建议
– 对于复杂查询:启用JIT编译,设置较低的成本阈值
– 对于简单查询:禁用JIT编译,或设置较高的成本阈值
– 对于内存充足的系统:增加jit_buffer_size
– 对于CPU资源充足的系统:启用JIT编译
– 对于高并发场景:禁用JIT编译,或设置较高的成本阈值
# 系统要求
– LLVM 9.0或更高版本
– 足够的内存:JIT编译需要额外内存
– 足够的CPU资源:JIT编译和执行需要CPU资源
2.3 JIT编译适用场景
JIT编译适用场景:
- 数据仓库查询:复杂的聚合和分析查询
- 报表生成:包含大量计算的报表查询
- 科学计算:包含复杂表达式的查询
- OLAP系统:在线分析处理系统
- 复杂查询:包含多个表连接和聚合的查询
Part03-生产环境项目实施方案
3.1 开启JIT编译
3.1.1 检查JIT编译是否可用
$ sudo -u pgsql psql -c “SHOW jit;”
jit
——
on
(1 row)
# 检查LLVM是否安装
$ sudo -u pgsql psql -c “SELECT pg_config(‘configure’);”
pg_config
——————————————————————
–prefix=/postgresql/fgapp –with-llvm –with-openssl –with-readline
(1 row)
# 检查JIT相关参数
$ sudo -u pgsql psql -c “SHOW jit_buffer_size;”
jit_buffer_size
—————-
16MB
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_above_cost;”
jit_above_cost
—————-
100000
(1 row)
3.1.2 启用JIT编译
$ sudo vi /postgresql/data/postgresql.conf
# 修改JIT编译参数
jit = on
jit_buffer_size = 32MB
jit_above_cost = 100000
jit_inline_above_cost = 500000
jit_optimize_above_cost = 500000
# 保存并退出
# 重新加载配置
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 验证修改结果
$ sudo -u pgsql psql -c “SHOW jit;”
jit
——
on
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_buffer_size;”
jit_buffer_size
—————-
32MB
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_above_cost;”
jit_above_cost
—————-
100000
(1 row)
3.2 JIT编译配置
3.2.1 调整JIT编译参数
$ sudo vi /postgresql/data/postgresql.conf
# 修改JIT编译参数
jit = on
jit_buffer_size = 64MB
jit_above_cost = 50000
jit_inline_above_cost = 300000
jit_optimize_above_cost = 300000
# 保存并退出
# 重新加载配置
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 验证修改结果
$ sudo -u pgsql psql -c “SHOW jit_buffer_size;”
jit_buffer_size
—————-
64MB
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_above_cost;”
jit_above_cost
—————-
50000
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_inline_above_cost;”
jit_inline_above_cost
———————-
300000
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_optimize_above_cost;”
jit_optimize_above_cost
————————
300000
(1 row)
3.2.2 禁用JIT编译
$ sudo vi /postgresql/data/postgresql.conf
# 修改JIT编译参数
jit = off
# 保存并退出
# 重新加载配置
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 验证修改结果
$ sudo -u pgsql psql -c “SHOW jit;”
jit
——
off
(1 row)
3.3 JIT编译监控
3.3.1 查看JIT编译执行计划
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
QUERY PLAN
——————————————————————————————————————————————–
Finalize GroupAggregate (cost=1000.58..1000.75 rows=5 width=46) (actual time=0.156..0.158 rows=5 loops=1)
Group Key: department
-> Gather (cost=1000.58..1000.67 rows=12 width=46) (actual time=0.148..0.152 rows=12 loops=1)
Workers Planned: 4
Workers Launched: 4
-> Partial GroupAggregate (cost=0.58..0.60 rows=3 width=46) (actual time=0.042..0.043 rows=3 loops=5)
Group Key: department
-> Parallel Seq Scan on fgedu_employees (cost=0.00..0.50 rows=2000 width=18) (actual time=0.007..0.014 rows=2000 loops=5)
Planning Time: 0.168 ms
Execution Time: 0.192 ms
JIT:
Functions: 8
Options: Inlining true, Optimization true, Expressions true, Deforming true
Timing: Generation 0.561 ms, Inlining 0.324 ms, Optimization 1.235 ms, Emission 0.876 ms, Total 2.996 ms
# 查看非JIT编译执行计划
$ sudo vi /postgresql/data/postgresql.conf
jit = off
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
QUERY PLAN
——————————————————————————————————————————————–
Finalize GroupAggregate (cost=1000.58..1000.75 rows=5 width=46) (actual time=0.187..0.189 rows=5 loops=1)
Group Key: department
-> Gather (cost=1000.58..1000.67 rows=12 width=46) (actual time=0.179..0.183 rows=12 loops=1)
Workers Planned: 4
Workers Launched: 4
-> Partial GroupAggregate (cost=0.58..0.60 rows=3 width=46) (actual time=0.050..0.051 rows=3 loops=5)
Group Key: department
-> Parallel Seq Scan on fgedu_employees (cost=0.00..0.50 rows=2000 width=18) (actual time=0.009..0.016 rows=2000 loops=5)
Planning Time: 0.132 ms
Execution Time: 0.215 ms
3.3.2 监控JIT编译性能
$ sudo -u pgsql psql -c “SELECT * FROM pg_stat_jit;”
reset_time | events | total_time | avg_time | stddev_time | min_time | max_time | calls | total_call_time | avg_call_time | stddev_call_time | min_call_time | max_call_time
—————————-+————-+—————–+—————–+——————-+—————–+—————–+————-+———————-+———————-+————————+———————-+———————-
2026-04-02 10:00:00.000000 | 1000 | 10000.000000000 | 10.000000000000 | 5.000000000000000 | 1.000000000000 | 50.000000000000 | 2000 | 20000.000000000000000 | 10.000000000000000000 | 5.000000000000000000 | 1.000000000000000000 | 50.000000000000000000
# 查看系统资源使用情况
$ top
# 查看CPU使用情况
$ mpstat -P ALL 1
# 查看内存使用情况
$ free -h
Part04-生产案例与实战讲解
4.1 开启JIT编译案例
4.1.1 案例描述
场景:一个数据分析系统,需要执行复杂的聚合查询,希望通过启用JIT编译来提高查询性能。
4.1.2 实施方案
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 16
On-line CPU(s) list: 0-15
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
Stepping: 2
CPU MHz: 2400.000
BogoMIPS: 4800.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 35840K
NUMA node0 CPU(s): 0-15
$ free -h
total used free shared buff/cache available
Mem: 31Gi 2.0Gi 25Gi 100Mi 4.0Gi 28Gi
Swap: 16Gi 0B 16Gi
# 2. 检查JIT编译是否可用
$ sudo -u pgsql psql -c “SHOW jit;”
jit
——
off
(1 row)
# 3. 启用JIT编译
$ sudo vi /postgresql/data/postgresql.conf
# 修改JIT编译参数
jit = on
jit_buffer_size = 64MB
jit_above_cost = 50000
jit_inline_above_cost = 300000
jit_optimize_above_cost = 300000
# 保存并退出
# 重新加载配置
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 4. 验证JIT编译配置
$ sudo -u pgsql psql -c “SHOW jit;”
jit
——
on
(1 row)
$ sudo -u pgsql psql -c “SHOW jit_buffer_size;”
jit_buffer_size
—————-
64MB
(1 row)
# 5. 测试JIT编译性能
# 测试复杂查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary), MAX(salary), MIN(salary) FROM fgedu_employees GROUP BY department ORDER BY AVG(salary) DESC;”
# 比较启用JIT前后的性能
# 启用JIT前
$ sudo vi /postgresql/data/postgresql.conf
jit = off
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary), MAX(salary), MIN(salary) FROM fgedu_employees GROUP BY department ORDER BY AVG(salary) DESC;”
# 启用JIT后
$ sudo vi /postgresql/data/postgresql.conf
jit = on
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary), MAX(salary), MIN(salary) FROM fgedu_employees GROUP BY department ORDER BY AVG(salary) DESC;”
4.2 JIT编译调优案例
4.2.1 案例描述
场景:一个数据仓库系统,需要执行大量复杂的分析查询,希望通过调优JIT编译参数来提高查询性能。
4.2.2 实施方案
$ sudo -u pgsql psql -d fgedu_production -c “SELECT query FROM pg_stat_statements ORDER BY mean_time DESC LIMIT 10;”
# 2. 测试不同JIT编译参数
# 测试默认参数
$ sudo vi /postgresql/data/postgresql.conf
jit = on
jit_buffer_size = 16MB
jit_above_cost = 100000
jit_inline_above_cost = 500000
jit_optimize_above_cost = 500000
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
# 测试调整jit_above_cost
$ sudo vi /postgresql/data/postgresql.conf
jit_above_cost = 50000
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
# 测试调整jit_buffer_size
$ sudo vi /postgresql/data/postgresql.conf
jit_buffer_size = 32MB
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
# 测试调整jit_buffer_size为64MB
$ sudo vi /postgresql/data/postgresql.conf
jit_buffer_size = 64MB
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT department, COUNT(*), AVG(salary) FROM fgedu_employees GROUP BY department;”
# 3. 分析测试结果
# 比较不同参数下的执行时间
# 分析JIT编译的时间开销
# 确定最佳JIT编译参数
# 4. 应用最佳配置
$ sudo vi /postgresql/data/postgresql.conf
jit = on
jit_buffer_size = 64MB
jit_above_cost = 50000
jit_inline_above_cost = 300000
jit_optimize_above_cost = 300000
# 保存并退出
# 重新加载配置
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
4.3 JIT编译性能测试案例
4.3.1 案例描述
场景:需要测试JIT编译对不同类型查询的性能影响,以确定JIT编译的最佳适用场景。
4.3.2 实施方案
$ sudo -u pgsql psql -d fgedu_production -c “CREATE TABLE fgedu_test (id serial PRIMARY KEY, value1 numeric(10,2), value2 numeric(10,2), value3 numeric(10,2), category varchar(50));”
$ sudo -u pgsql psql -d fgedu_production -c “INSERT INTO fgedu_test (value1, value2, value3, category) SELECT random() * 10000, random() * 10000, random() * 10000, ‘Category ‘ || (i % 10) FROM generate_series(1, 1000000) i;”
# 2. 测试不同类型的查询
# 测试聚合查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT category, COUNT(*), AVG(value1), SUM(value2), MAX(value3) FROM fgedu_test GROUP BY category;”
# 测试表达式查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT id, value1, value2, value3, value1 * value2 / value3 AS result FROM fgedu_test WHERE value1 > 5000 AND value2 < 8000;"
# 测试连接查询
$ sudo -u pgsql psql -d fgedu_production -c "EXPLAIN ANALYZE SELECT t1.id, t1.value1, t2.value2 FROM fgedu_test t1 JOIN fgedu_test t2 ON t1.id = t2.id WHERE t1.value1 > 5000;”
# 测试排序查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT * FROM fgedu_test ORDER BY value1 DESC, value2 ASC LIMIT 1000;”
# 3. 比较启用和禁用JIT编译的性能
# 禁用JIT编译
$ sudo vi /postgresql/data/postgresql.conf
jit = off
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 测试聚合查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT category, COUNT(*), AVG(value1), SUM(value2), MAX(value3) FROM fgedu_test GROUP BY category;”
# 启用JIT编译
$ sudo vi /postgresql/data/postgresql.conf
jit = on
$ sudo -u pgsql psql -c “SELECT pg_reload_conf();”
# 测试聚合查询
$ sudo -u pgsql psql -d fgedu_production -c “EXPLAIN ANALYZE SELECT category, COUNT(*), AVG(value1), SUM(value2), MAX(value3) FROM fgedu_test GROUP BY category;”
# 4. 分析测试结果
# 比较启用和禁用JIT编译的执行时间
# 分析JIT编译对不同查询类型的影响
# 确定JIT编译的最佳适用场景
Part05-风哥经验总结与分享
5.1 PostgreSQL JIT编译最佳实践
PostgreSQL JIT编译最佳实践:
- 根据硬件配置调优:根据服务器的CPU和内存配置调整JIT编译参数
- 根据工作负载调优:根据查询类型和复杂度调整JIT编译参数
- 测试验证:在测试环境中测试JIT编译的效果,确定最佳配置
- 监控JIT编译:监控JIT编译的执行情况,及时发现和解决问题
- 合理设置成本阈值:根据查询复杂度设置合适的jit_above_cost值
- 调整缓冲区大小:根据内存情况调整jit_buffer_size值
- 选择性启用:在适合的场景中启用JIT编译,避免在不适合的场景中使用
- 定期审查:定期审查JIT编译的效果,根据业务需求和系统变化调整配置
5.2 JIT编译常见问题
JIT编译常见问题及解决方案:
- 编译时间过长:导致查询执行时间增加,解决方案:调整jit_above_cost参数,只对复杂查询启用JIT编译
- 内存使用过高:JIT编译需要额外内存,解决方案:调整jit_buffer_size参数,避免内存不足
- CPU使用过高:JIT编译和执行需要CPU资源,解决方案:在CPU资源充足的系统中启用JIT编译
- 性能下降:对于简单查询,JIT编译可能导致性能下降,解决方案:设置较高的jit_above_cost值
- LLVM版本不兼容:JIT编译需要特定版本的LLVM,解决方案:确保安装兼容的LLVM版本
- 编译失败:JIT编译可能失败,解决方案:检查系统环境和LLVM安装
- 调试困难:JIT编译生成的代码难以调试,解决方案:在调试时禁用JIT编译
- 系统负载增加:JIT编译可能增加系统负载,解决方案:在低峰期启用JIT编译,或限制JIT编译的使用
5.3 JIT编译调优技巧
JIT编译调优技巧:
- 成本阈值调优:
- 对于复杂查询:设置较低的jit_above_cost值
- 对于简单查询:设置较高的jit_above_cost值
- 根据查询执行时间调整成本阈值
- 缓冲区大小调优:
- 内存充足的系统:增加jit_buffer_size值
- 内存有限的系统:减少jit_buffer_size值
- 根据查询复杂度调整缓冲区大小
- 适用场景选择:
- 数据仓库:启用JIT编译
- OLAP系统:启用JIT编译
- OLTP系统:禁用JIT编译,或设置较高的成本阈值
- 高并发场景:禁用JIT编译
- 系统调优:
- 使用高速CPU:JIT编译和执行需要CPU资源
- 增加内存:JIT编译需要额外内存
- 优化存储:减少IO瓶颈,提高查询性能
- 监控系统资源:避免资源不足
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
