开发者
鲲鹏服务器上 PostgreSQL 查询性能波动排查与优化
鲲鹏服务器上 PostgreSQL 查询性能波动排查与优化
原创
发表于05/08
170

问题描述

将 OLAP 业务数据库从 x86 迁移到鲲鹏 920(64 核 / 256GB 内存 / 1TB NVMe SSD),PostgreSQL 14 大部分查询正常,但某些复杂聚合查询的响应时间波动很大——快的 2 秒完成,慢的要 8 秒以上。用 EXPLAIN ANALYZE 检查,执行计划相同,但每次实际耗时差异明显。

排查过程

# 查看当前 PostgreSQL 配置
psql -c "SHOW shared_buffers; SHOW work_mem; SHOW effective_cache_size;"

# 输出:
# shared_buffers = 128MB        <-- 默认值太小
# work_mem = 4MB
# effective_cache_size = 4GB

# 检查大页配置
cat /proc/meminfo | grep -i huge

# 输出:
# HugePages_Total:       0      <-- 未配置大页
# HugePages_Free:        0

进一步检查 PostgreSQL 是否使用了大页:

# 查看 PostgreSQL 进程的内存映射
pmap -x $(pidof postgres) | grep -i huge
# 无输出,说明未使用大页

# 检查 shared_buffers 是否覆盖
psql -c "SELECT pg_size_pretty(pg_shmem_size());"
# 输出:128 MB
```

问题定位:`shared_buffers` 仅 128MB(默认值),远未利用鲲鹏的大内存优势。同时系统未配置大页,PostgreSQL 的共享内存走普通页表,TLB miss 频繁导致内存访问不稳定。

## 优化方案

**第一步:配置系统大页**

```bash
# 计算需要的大页数量(shared_buffers 计划设为 64GB,每页 2MB)
# 64GB / 2MB = 32768 页,预留余量设为 35000

echo 35000 > /proc/sys/vm/nr_hugepages

# 验证
cat /proc/meminfo | grep HugePages
# HugePages_Total:   35000
# HugePages_Free:    35000

# 永久生效
echo "vm.nr_hugepages = 35000" >> /etc/sysctl.conf
```

**第二步:优化 PostgreSQL 配置**

```bash
# 编辑 postgresql.conf
cat >> /var/lib/pgsql/data/postgresql.conf << 'EOF'
# 内存配置(鲲鹏 256GB 内存)
shared_buffers = 64GB
effective_cache_size = 200GB
work_mem = 256MB
maintenance_work_mem = 2GB

# 启用大页
huge_pages = on

# 并行查询(鲲鹏多核优势)
max_parallel_workers_per_gather = 16
max_parallel_workers = 32
max_parallel_maintenance_workers = 8

# WAL 配置
wal_buffers = 64MB
checkpoint_completion_target = 0.9
EOF
```

**第三步:重启 PostgreSQL 并验证**

```bash
# 重启服务
systemctl restart postgresql

# 验证大页是否生效
pmap -x $(pidof postgres) | grep -i huge
# 输出应显示大页内存映射

# 验证配置
psql -c "SHOW shared_buffers; SHOW huge_pages;"
# shared_buffers = 64GB
# huge_pages = on

效果验证

对波动明显的聚合查询进行多次测试:

-- 测试查询
EXPLAIN ANALYZE SELECT 
    date_trunc('hour', created_at) AS hour,
    COUNT(*) AS cnt,
    AVG(amount) AS avg_amount
FROM orders
WHERE created_at >= '2024-01-01'
GROUP BY date_trunc('hour', created_at)
ORDER BY hour;
指标优化前优化后
查询响应时间(平均)4.2s1.8s
查询响应时间(P99)8.5s2.1s
响应时间波动范围2s - 8.5s1.6s - 2.3s
shared_buffers 命中率78%96%
TLB miss 率(perf 测)12%2%

小结

鲲鹏上 PostgreSQL 查询性能波动的根因是 shared_buffers 默认值太小且未启用大页,内存访问走普通页表导致 TLB miss 不稳定。核心优化点:配置系统大页(nr_hugepages)、将 shared_buffers 设为物理内存的 25%-30%、启用 huge_pages = on、利用多核优势调大并行查询参数。建议用 pmap -x 验证大页是否生效,用 EXPLAIN ANALYZE 多次执行观察耗时波动。

收藏举报
Level 1
0
帖子
0
粉丝
0
获赞