postgresql cpu高什么原因
2026/7/31 18:59:18 网站建设 项目流程

PostgreSQL CPU 高的常见原因及排查思路如下:


一、最常见原因

1.慢查询 / 缺少索引

  • 大表全表扫描、未使用索引的 WHERE/JOIN 条件

  • 复杂聚合、窗口函数、递归 CTE 消耗大量 CPU

  • 排查pg_stat_statements查看总耗时/调用次数最高的 SQL

2.并发连接过多

  • 连接数远超 CPU 核心数,上下文切换开销大

  • 大量空闲连接也会占用内存和少量 CPU

  • 排查pg_stat_activity查看活跃/空闲连接数

3.锁竞争与等待

  • 长时间持有锁导致其他查询排队,看似"卡死"实则 CPU 在等待

  • 死锁检测、行级锁竞争

  • 排查pg_locks+pg_stat_activity关联分析

4.VACUUM / AUTOVACUUM 频繁运行

  • 表膨胀严重,autovacuum 持续工作

  • 大量死元组需要清理

  • 排查pg_stat_user_tables查看n_dead_tuplast_vacuumlast_autovacuum

5.checkpoint / WAL 写入压力

  • checkpoint 过于频繁,刷脏页压力大

  • checkpoint_completion_target配置不当

  • 排查pg_stat_bgwriter,日志中是否有 "checkpoint starting" 过于频繁


二、其他可能原因

表格

原因说明
大量短连接连接建立/断开开销,建议用连接池(PgBouncer)
不合理的配置shared_buffers过小导致频繁磁盘 I/O 间接推高 CPU;work_mem过小导致大量磁盘排序
数据类型隐式转换导致索引失效,走全表扫描
触发器/存储过程逻辑复杂在数据库层做过多业务计算
逻辑复制槽滞后导致 WAL 堆积,后台进程持续工作
外部扩展/FDW外部表查询拉取大量数据在本地处理

三、快速排查命令

sql

-- 1. 查看当前活跃查询及运行时间 SELECT pid, usename, state, query_start, now() - query_start AS duration, query FROM pg_stat_activity WHERE state = 'active' AND query NOT LIKE '%pg_stat_activity%' ORDER BY duration DESC; -- 2. 查看慢查询统计(需先安装 pg_stat_statements) SELECT query, calls, total_exec_time, mean_exec_time, rows FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10; -- 3. 查看表膨胀和 vacuum 情况 SELECT schemaname, relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum, last_analyze FROM pg_stat_user_tables WHERE n_dead_tup > 10000 ORDER BY n_dead_tup DESC; -- 4. 查看锁等待 SELECT blocked_locks.pid AS blocked_pid, blocked_activity.usename AS blocked_user, blocking_locks.pid AS blocking_pid, blocking_activity.usename AS blocking_user, blocked_activity.query AS blocked_statement, blocking_activity.query AS blocking_statement FROM pg_catalog.pg_locks blocked_locks JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid WHERE NOT blocked_locks.granted;

四、建议的解决方向

  1. 定位具体进程:用top -H -p $(pgrep postgres)看是哪个 PostgreSQL 后端进程占 CPU,再对应到具体 SQL

  2. 优化 SQL:加索引、改写查询、分区大表

  3. 调整配置shared_bufferswork_memeffective_cache_sizemaintenance_work_mem

  4. 控制连接:使用 PgBouncer 连接池

  5. 治理表膨胀:手动 VACUUM FULL(注意锁表)或调整 autovacuum 参数

  6. 升级硬件:如确实是计算密集型查询,考虑垂直扩容

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询