纲要
PostgreSQL基础性能调优的核心原则:帕累托法则(二八法则)- 调优辅助工具:
pgtune与pg_configurator - 内存相关参数调优
shared_buffers------ 共享内存缓冲区work_mem------ 每个后端进程的工作内存maintenance_work_mem------ 维护操作专用内存effective_cache_size------ 优化器缓存估算(非实际分配)temp_buffers------ 临时表缓冲区
- 检查点(
Checkpoint)相关参数调优checkpoint_timeoutcheckpoint_completion_targetmax_wal_size/min_wal_size
- 自动清理(
Autovacuum)参数调优autovacuum_max_workersautovacuum_naptimeautovacuum_vacuum_cost_limit/autovacuum_vacuum_cost_delay
- 查询规划器成本常量调优
random_page_costseq_page_cost
- 配置文件生效规则:以最后一次出现的参数值为准
二八法则:性能调优的核心指导思想
PostgreSQL 的默认配置面向兼容性和通用场景设计,并未针对服务器的具体硬件资源(CPU 核心数、内存大小、磁盘类型)做针对性优化。因此,数据库安装完成后,首要任务便是根据实际硬件配置与业务负载特征,对关键参数进行基础调整。
在调优实践中,帕累托法则(Pareto Principle,即二八法则) 是一个极为实用的指导原则:80% 的性能收益往往来自于对 20% 的关键参数进行调整。PostgreSQL 拥有数百个配置参数,但在绝大多数业务系统的初期阶段,只需将内存、检查点、自动清理和 I/O 成本这几类核心参数调整到位,即可获得显著的性能提升。无需一开始便深入研究全部参数,也无需盲目照搬他人的配置文件。
调优辅助工具:pgtune 与 pg_configurator
在手动调整参数之前,可借助自动化工具生成一份基于硬件规格的基础配置,再根据实际业务场景进行微调。
pgtune
pgtune 是一款经典的 PostgreSQL 配置向导工具。它根据用户输入的硬件信息(CPU 数量、内存大小、磁盘类型等)和预期工作负载类型(OLTP、数据仓库、混合负载等),自动计算并生成推荐的 postgresql.conf 配置参数。
bash
# pgtune 命令行示例(以 pgtune 的 Python 实现为例)
pgtune -i postgresql.conf -o postgresql-new.conf
pgtune 也提供在线 Web 版本,用户可通过表单填写服务器规格后一键生成配置。生成后的参数可直接追加到 postgresql.conf 文件末尾,或通过 ALTER SYSTEM 命令设置。
pg_configurator
pg_configurator 是一个更为现代化的图形化配置工具。与 pgtune 相比,它的可配置项更加丰富,支持设置日志回收策略、数据可靠性级别、备库数量等高级选项。其核心原理与 pgtune 一致:根据输入的硬件与业务参数生成优化后的配置参数。
建议:先使用上述工具生成一份基础配置,再结合实际监控数据与业务特点进行针对性微调。
内存相关参数调优
PostgreSQL 采用多进程架构,进程间通信依赖共享内存。以下是几个最核心的内存参数。
shared_buffers
shared_buffers 是 PostgreSQL 的共享内存缓冲区,用于缓存数据页(表数据和索引数据)。所有增删改查操作均在 shared_buffers 池中进行。
- 默认值:128MB(通常过小)
- 推荐设置 :服务器物理内存的 25%
- 内存 < 2GB:设为总内存的 20%
- 内存 < 32GB:设为总内存的 25%
- 内存 > 32GB:可设为 8GB 左右
配置
postgresql
# postgresql.conf
shared_buffers = 4GB # 假设服务器内存为 16GB
为何不建议设为 80%~90%?PostgreSQL 采用独特的双缓存架构 :数据库自身管理 shared_buffers,操作系统同时也有自己的页面缓存(Page Cache)。两者共同作用,需为操作系统缓存预留足够内存。
work_mem
work_mem 是每个后端进程在执行排序(ORDER BY、DISTINCT)、哈希连接(Hash Join)等操作时可用的内存量。此为私有内存,每个会话的每个执行节点都可能消耗此内存。
- 默认值:4MB
- 风险:设置过大且并发连接数较高时,可能导致内存溢出(OOM)
- 建议:在会话级别按需设置,而非全局设置过大
sql
-- 会话级别设置 work_mem(仅对当前会话生效)
SET work_mem = '64MB';
-- 执行大型排序或哈希操作
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM large_table ORDER BY large_column;
postgresql
# 全局默认值(谨慎设置)
work_mem = '32MB' # 保守值,建议从 32-64MB 起步
maintenance_work_mem
maintenance_work_mem 专用于维护性操作的内存,包括 VACUUM、CREATE INDEX、REINDEX、ALTER TABLE ADD FOREIGN KEY 等。
- 默认值:64MB
- 推荐设置:每 1GB 内存配置 50MB,即 16GB 内存可设为 800MB
- 上限:一般不超过 1GB~2GB
配置
postgresql
# postgresql.conf
maintenance_work_mem = '1GB'
effective_cache_size
effective_cache_size 用于告知查询优化器操作系统和数据库可用的磁盘缓存总量。此参数并非实际分配内存,仅影响优化器的执行计划选择。
-
推荐设置 :服务器总内存的 50%~75%
postgresql# postgresql.conf effective_cache_size = '12GB' # 假设服务器内存为 16GB
temp_buffers
temp_buffers 用于临时表操作的内存缓冲。每个会话可独立设置。
-
默认值:8MB
sql-- 会话级别设置 SET temp_buffers = '64MB'; CREATE TEMP TABLE temp_data AS SELECT * FROM large_table;
检查点(Checkpoint)参数调优
检查点(Checkpoint)是将内存中的脏页(Dirty Pages)刷写到磁盘的操作,用于保证数据一致性。检查点过于频繁会增加 I/O 压力;间隔过长则会延长崩溃恢复时间。
checkpoint_timeout
两次自动检查点之间的最大时间间隔。
-
默认值:5 分钟(300 秒)
-
取值范围:30 秒 ~ 1 小时
-
推荐设置 :15~30 分钟
postgresql# postgresql.conf checkpoint_timeout = '15min'
checkpoint_completion_target
检查点完成的目标比例,即在下一次检查点开始前,本次检查点应完成的比例。
-
默认值:0.5(50%)
-
取值范围:0.0 ~ 1.0
-
推荐设置 :0.9(让写入更平滑,避免 I/O 尖峰)
postgresql# postgresql.conf checkpoint_completion_target = 0.9
max_wal_size / min_wal_size
控制 WAL(Write-Ahead Log)日志总量的上下限。当 WAL 总量达到 max_wal_size 时会触发检查点。
-
默认值 :
max_wal_size = 1GB,min_wal_size = 80MB -
推荐设置:根据实际业务写入量调整,通常可适当增大
postgresql# postgresql.conf max_wal_size = '4GB' min_wal_size = '1GB'
自动清理(Autovacuum)参数调优
PostgreSQL 采用 MVCC(多版本并发控制)机制,更新和删除操作会产生"过期"元组(Dead Tuples),需通过 VACUUM 进行清理回收。autovacuum 是 PostgreSQL 的自动清理守护进程。
autovacuum_max_workers
同时运行的 autovacuum 工作进程的最大数量。
-
默认值:3
-
推荐设置 :根据 CPU 核心数调整,32 核可设为 5~10
postgresql# postgresql.conf autovacuum_max_workers = 5
autovacuum_naptime
autovacuum 启动器检查各数据库并触发清理任务的时间间隔。
-
默认值:1 分钟(1min)
-
推荐设置:通常保持默认即可
postgresql# postgresql.conf autovacuum_naptime = '1min'
autovacuum_vacuum_cost_limit / autovacuum_vacuum_cost_delay
控制 autovacuum 的 I/O 成本上限与延迟,用于限制清理操作对正常业务的影响。
- 默认值 :
autovacuum_vacuum_cost_limit = -1(使用vacuum_cost_limit的值,默认为 200),autovacuum_vacuum_cost_delay = 2ms - 推荐设置 :
- SSD 存储:可将
autovacuum_vacuum_cost_limit设为 1000~2000 - NVMe SSD:可设为 2000~10000
- SSD 存储:可将
配置
postgresql
# postgresql.conf
autovacuum_vacuum_cost_limit = 2000
autovacuum_vacuum_cost_delay = '2ms'
查询规划器成本常量调优
PostgreSQL 的查询优化器基于成本模型选择执行计划。seq_page_cost 与 random_page_cost 是其中两个最重要的 I/O 成本常量。
seq_page_cost 与 random_page_cost
seq_page_cost:顺序读取一页的成本,默认 1.0random_page_cost:随机读取一页的成本,默认 4.0
两者的比值决定了优化器在顺序扫描(Sequential Scan)与索引扫描(Index Scan)之间的偏好。
postgresql
# postgresql.conf(适用于 NVMe SSD 或高性能存储)
random_page_cost = 1.5
seq_page_cost = 1.0
注意 :虽然系统允许将 random_page_cost 设为小于 seq_page_cost,但这在物理上是不合理的。对于全内存缓存的数据库,可考虑将两者设为相等。
调优原理
可将数据库选择执行计划的过程类比为从成都到北京的出行方式选择:
| 出行方式 | 时间成本 | 金钱成本 | 对应数据库操作 |
|---|---|---|---|
| 飞机 | 低 | 高 | 索引扫描(随机 I/O) |
| 高铁 | 中 | 中 | 位图扫描 |
| 自驾 | 高 | 低 | 顺序扫描(顺序 I/O) |
random_page_cost 与 seq_page_cost 的比值就是优化器判断"走索引"还是"走全表扫描"的决策依据。对于现代 SSD 或 NVMe 存储,随机 I/O 与顺序 I/O 的性能差距已大幅缩小,因此应适当降低 random_page_cost。
配置文件生效规则
PostgreSQL 的 postgresql.conf 配置文件采用以最后一次出现的参数值为准的生效规则。若同一参数在文件中出现多次,仅最后一次生效。
因此,建议将调优后的参数统一追加至文件末尾,并添加注释说明:
postgresql
# ============================================
# 以下为 pgtune 生成的调优参数(2026-08-13)
# ============================================
shared_buffers = 4GB
work_mem = 32MB
maintenance_work_mem = 1GB
effective_cache_size = 12GB
checkpoint_timeout = '15min'
checkpoint_completion_target = 0.9
max_wal_size = '4GB'
random_page_cost = 1.5
autovacuum_max_workers = 5
autovacuum_vacuum_cost_limit = 2000
修改配置文件后,需重启 PostgreSQL 或执行 pg_ctl reload 使参数生效(部分参数需重启)。
API 速览
本博客涉及的核心 PostgreSQL 配置参数 API 汇总如下:
| 参数名 | 所属类别 | 类型 | 默认值 | 推荐范围 | 生效方式 |
|---|---|---|---|---|---|
shared_buffers |
内存 | integer | 128MB | 总内存的 20%~25% | 重启 |
work_mem |
内存 | integer | 4MB | 32~64MB(起步) | 会话/全局 |
maintenance_work_mem |
内存 | integer | 64MB | 每 1GB 内存 50MB | 会话/全局 |
effective_cache_size |
内存 | integer | 4GB | 总内存的 50%~75% | 重载 |
temp_buffers |
内存 | integer | 8MB | 视临时表大小而定 | 会话/全局 |
checkpoint_timeout |
检查点 | integer | 300s | 15~30min | 重载 |
checkpoint_completion_target |
检查点 | floating | 0.5 | 0.8~0.9 | 重载 |
max_wal_size |
检查点 | integer | 1GB | 视业务写入量而定 | 重载 |
autovacuum_max_workers |
自动清理 | integer | 3 | CPU 核数的 1/4~1/3 | 重启 |
autovacuum_naptime |
自动清理 | integer | 1min | 保持默认 | 重载 |
autovacuum_vacuum_cost_limit |
自动清理 | integer | -1 (200) | 1000~10000(SSD) | 重载 |
random_page_cost |
查询规划 | floating | 4.0 | 1.0~2.0(SSD) | 重载 |
seq_page_cost |
查询规划 | floating | 1.0 | 1.0 | 重载 |
参数生效方式说明:
- 重启:需重启 PostgreSQL 服务方可生效
- 重载 :执行
SELECT pg_reload_conf()或pg_ctl reload即可生效,无需重启
Demo 简单示例
以下 Demo 演示了如何使用 Node.js 和 pg 驱动连接 PostgreSQL,并通过 SHOW 命令查看当前配置参数,以及通过 SET 命令在会话级别调整 work_mem。
运行说明
bash
# 1. 初始化项目
mkdir pg-tuning-demo && cd pg-tuning-demo
npm init -y
# 2. 安装依赖
npm install pg
# 3. 创建 index.js 文件(内容见下方)
# 4. 运行
node index.js
代码说明
js
const { Client } = require('pg');
// PostgreSQL 连接配置
const config = {
host: 'localhost',
port: 5432,
database: 'postgres',
user: 'postgres',
password: 'your_password',
};
async function main() {
const client = new Client(config);
try {
await client.connect();
console.log('✅ 已连接到 PostgreSQL');
// 1. 查看当前关键参数
const params = [
'shared_buffers',
'work_mem',
'maintenance_work_mem',
'effective_cache_size',
'checkpoint_timeout',
'max_wal_size',
'random_page_cost',
'autovacuum_max_workers'
];
console.log('\n📊 当前配置参数:');
for (const param of params) {
const res = await client.query(`SHOW ${param};`);
console.log(` ${param} = ${res.rows[0][param]}`);
}
// 2. 会话级别调整 work_mem
console.log('\n⚙️ 会话级别调整 work_mem...');
await client.query(`SET work_mem = '64MB';`);
const res = await client.query(`SHOW work_mem;`);
console.log(` work_mem (当前会话) = ${res.rows[0].work_mem}`);
// 3. 创建测试表并插入数据
await client.query(`
DROP TABLE IF EXISTS tuning_demo;
CREATE TABLE tuning_demo (
id SERIAL PRIMARY KEY,
value INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
`);
console.log('\n📋 已创建测试表 tuning_demo');
// 4. 插入 10 万条测试数据
console.log('📝 插入 100,000 条测试数据...');
await client.query(`
INSERT INTO tuning_demo (value)
SELECT generate_series(1, 100000);
`);
console.log('✅ 数据插入完成');
// 5. 执行排序查询,验证 work_mem 效果
console.log('\n🔍 执行排序查询 (ORDER BY value DESC)...');
const explainRes = await client.query(`
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM tuning_demo ORDER BY value DESC LIMIT 100;
`);
console.log('\n📈 执行计划:');
explainRes.rows.forEach(row => {
console.log(` ${row['QUERY PLAN']}`);
});
} catch (err) {
console.error('❌ 错误:', err.message);
} finally {
await client.end();
console.log('\n🔌 连接已关闭');
}
}
main();
对应的 PostgreSQL 原生指令
sql
-- 查看当前配置参数
SHOW shared_buffers;
SHOW work_mem;
SHOW maintenance_work_mem;
SHOW effective_cache_size;
SHOW checkpoint_timeout;
SHOW max_wal_size;
SHOW random_page_cost;
SHOW autovacuum_max_workers;
-- 会话级别设置 work_mem
SET work_mem = '64MB';
-- 创建测试表
DROP TABLE IF EXISTS tuning_demo;
CREATE TABLE tuning_demo (
id SERIAL PRIMARY KEY,
value INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
-- 插入测试数据
INSERT INTO tuning_demo (value)
SELECT generate_series(1, 100000);
-- 查看执行计划
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM tuning_demo ORDER BY value DESC LIMIT 100;
技术点总结
pg驱动连接 :使用 Node.js 的pg库连接 PostgreSQL 数据库SHOW命令:查看当前生效的配置参数值SET命令 :在会话级别动态调整work_mem,无需重启数据库EXPLAIN (ANALYZE, BUFFERS):分析查询执行计划,观察内存与 I/O 使用情况- 参数分层管理 :全局参数(
postgresql.conf)与会话级参数(SET)的优先级关系
多语言 Demo 示例
以下分别提供 Go、Python、Java 三种语言的完整可运行示例,功能与前述 Node.js 版本一致:连接 PostgreSQL,查看关键配置参数,会话级调整 work_mem,创建测试表并插入 10 万条数据,最后执行带 EXPLAIN (ANALYZE, BUFFERS) 的查询并输出执行计划。
Go 语言示例
使用 lib/pq 或 pgx 驱动,此处采用 pgx/v5(推荐)。
运行说明
bash
# 初始化模块
go mod init pg-tuning-demo
go get github.com/jackc/pgx/v5
# 运行
go run main.go
代码 (main.go)
go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/jackc/pgx/v5"
)
func main() {
ctx := context.Background()
// 连接配置
connStr := "postgres://postgres:your_password@localhost:5432/postgres"
conn, err := pgx.Connect(ctx, connStr)
if err != nil {
log.Fatalf("无法连接数据库: %v", err)
}
defer conn.Close(ctx)
fmt.Println("✅ 已连接到 PostgreSQL")
// 1. 查看当前关键参数
params := []string{
"shared_buffers",
"work_mem",
"maintenance_work_mem",
"effective_cache_size",
"checkpoint_timeout",
"max_wal_size",
"random_page_cost",
"autovacuum_max_workers",
}
fmt.Println("\n📊 当前配置参数:")
for _, p := range params {
var val string
err = conn.QueryRow(ctx, fmt.Sprintf("SHOW %s;", p)).Scan(&val)
if err != nil {
log.Printf("获取参数 %s 失败: %v", p, err)
continue
}
fmt.Printf(" %s = %s\n", p, val)
}
// 2. 会话级别调整 work_mem
fmt.Println("\n⚙️ 会话级别调整 work_mem...")
_, err = conn.Exec(ctx, "SET work_mem = '64MB';")
if err != nil {
log.Fatalf("设置 work_mem 失败: %v", err)
}
var workMem string
err = conn.QueryRow(ctx, "SHOW work_mem;").Scan(&workMem)
if err == nil {
fmt.Printf(" work_mem (当前会话) = %s\n", workMem)
}
// 3. 创建测试表
fmt.Println("\n📋 创建测试表 tuning_demo...")
_, err = conn.Exec(ctx, `
DROP TABLE IF EXISTS tuning_demo;
CREATE TABLE tuning_demo (
id SERIAL PRIMARY KEY,
value INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
`)
if err != nil {
log.Fatalf("创建表失败: %v", err)
}
// 4. 插入 10 万条数据
fmt.Println("📝 插入 100,000 条测试数据...")
_, err = conn.Exec(ctx, `
INSERT INTO tuning_demo (value)
SELECT generate_series(1, 100000);
`)
if err != nil {
log.Fatalf("插入数据失败: %v", err)
}
fmt.Println("✅ 数据插入完成")
// 5. 执行排序查询并查看执行计划
fmt.Println("\n🔍 执行排序查询 (ORDER BY value DESC)...")
rows, err := conn.Query(ctx, `
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM tuning_demo ORDER BY value DESC LIMIT 100;
`)
if err != nil {
log.Fatalf("查询执行计划失败: %v", err)
}
defer rows.Close()
fmt.Println("\n📈 执行计划:")
for rows.Next() {
var planLine string
if err := rows.Scan(&planLine); err != nil {
log.Printf("扫描结果失败: %v", err)
continue
}
fmt.Printf(" %s\n", planLine)
}
fmt.Println("\n🔌 连接已关闭")
}
对应的 PostgreSQL 原生指令(与 Node 版相同,此处省略重复,请参照前文)
Python 语言示例
使用 psycopg2(或 asyncpg,此处选用同步的 psycopg2)。
运行说明
bash
# 创建虚拟环境(可选)
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# 安装依赖
pip install psycopg2-binary
# 运行
python main.py
代码 (main.py)
python
import psycopg2
from psycopg2 import sql
def main():
# 连接配置
conn = psycopg2.connect(
host="localhost",
port=5432,
database="postgres",
user="postgres",
password="your_password"
)
conn.autocommit = True
cur = conn.cursor()
print("✅ 已连接到 PostgreSQL")
# 1. 查看当前关键参数
params = [
"shared_buffers",
"work_mem",
"maintenance_work_mem",
"effective_cache_size",
"checkpoint_timeout",
"max_wal_size",
"random_page_cost",
"autovacuum_max_workers",
]
print("\n📊 当前配置参数:")
for p in params:
cur.execute(sql.SQL("SHOW {};").format(sql.Identifier(p)))
val = cur.fetchone()[0]
print(f" {p} = {val}")
# 2. 会话级别调整 work_mem
print("\n⚙️ 会话级别调整 work_mem...")
cur.execute("SET work_mem = '64MB';")
cur.execute("SHOW work_mem;")
work_mem = cur.fetchone()[0]
print(f" work_mem (当前会话) = {work_mem}")
# 3. 创建测试表
print("\n📋 创建测试表 tuning_demo...")
cur.execute("""
DROP TABLE IF EXISTS tuning_demo;
CREATE TABLE tuning_demo (
id SERIAL PRIMARY KEY,
value INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
""")
# 4. 插入 10 万条数据
print("📝 插入 100,000 条测试数据...")
cur.execute("""
INSERT INTO tuning_demo (value)
SELECT generate_series(1, 100000);
""")
print("✅ 数据插入完成")
# 5. 执行排序查询并查看执行计划
print("\n🔍 执行排序查询 (ORDER BY value DESC)...")
cur.execute("""
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM tuning_demo ORDER BY value DESC LIMIT 100;
""")
rows = cur.fetchall()
print("\n📈 执行计划:")
for row in rows:
print(f" {row[0]}")
cur.close()
conn.close()
print("\n🔌 连接已关闭")
if __name__ == "__main__":
main()
对应的 PostgreSQL 原生指令(同前,略)
Java 语言示例
使用 JDBC 驱动(org.postgresql:postgresql)和 Maven 构建。
运行说明
bash
# 创建 Maven 项目结构
mkdir -p pg-tuning-demo/src/main/java
cd pg-tuning-demo
# 创建 pom.xml(内容见下方)
# 将 Java 源码放入 src/main/java/PgTuningDemo.java
# 编译并运行
mvn compile exec:java -Dexec.mainClass="PgTuningDemo"
pom.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>pg-tuning-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
</dependency>
</dependencies>
</project>
代码 (PgTuningDemo.java)
java
import java.sql.*;
import java.util.Arrays;
import java.util.List;
public class PgTuningDemo {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/postgres";
String user = "postgres";
String password = "your_password";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
System.out.println("✅ 已连接到 PostgreSQL");
// 1. 查看当前关键参数
List<String> params = Arrays.asList(
"shared_buffers",
"work_mem",
"maintenance_work_mem",
"effective_cache_size",
"checkpoint_timeout",
"max_wal_size",
"random_page_cost",
"autovacuum_max_workers"
);
System.out.println("\n📊 当前配置参数:");
for (String p : params) {
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SHOW " + p + ";")) {
if (rs.next()) {
System.out.println(" " + p + " = " + rs.getString(1));
}
}
}
// 2. 会话级别调整 work_mem
System.out.println("\n⚙️ 会话级别调整 work_mem...");
try (Statement stmt = conn.createStatement()) {
stmt.execute("SET work_mem = '64MB';");
}
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SHOW work_mem;")) {
if (rs.next()) {
System.out.println(" work_mem (当前会话) = " + rs.getString(1));
}
}
// 3. 创建测试表
System.out.println("\n📋 创建测试表 tuning_demo...");
try (Statement stmt = conn.createStatement()) {
stmt.execute("DROP TABLE IF EXISTS tuning_demo;");
stmt.execute("""
CREATE TABLE tuning_demo (
id SERIAL PRIMARY KEY,
value INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
""");
}
// 4. 插入 10 万条数据
System.out.println("📝 插入 100,000 条测试数据...");
try (Statement stmt = conn.createStatement()) {
stmt.execute("""
INSERT INTO tuning_demo (value)
SELECT generate_series(1, 100000);
""");
}
System.out.println("✅ 数据插入完成");
// 5. 执行排序查询并查看执行计划
System.out.println("\n🔍 执行排序查询 (ORDER BY value DESC)...");
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("""
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM tuning_demo ORDER BY value DESC LIMIT 100;
""")) {
System.out.println("\n📈 执行计划:");
while (rs.next()) {
System.out.println(" " + rs.getString(1));
}
}
System.out.println("\n🔌 连接已关闭");
} catch (SQLException e) {
System.err.println("❌ 错误: " + e.getMessage());
e.printStackTrace();
}
}
}
对应的 PostgreSQL 原生指令(同前,略)
各语言技术点对比
| 语言 | 驱动/库 | 连接方式 | 参数查询 | 会话级 SET | 执行计划 |
|---|---|---|---|---|---|
| Node.js | pg |
Client 连接 |
client.query('SHOW ...') |
client.query('SET ...') |
EXPLAIN (ANALYZE, BUFFERS) |
| Go | pgx/v5 |
pgx.Connect |
conn.QueryRow |
conn.Exec |
conn.Query |
| Python | psycopg2 |
connect() + cursor |
cur.execute(sql.SQL(...)) |
cur.execute(...) |
cur.execute(...) + fetchall |
| Java | JDBC (PostgreSQL) | DriverManager.getConnection |
Statement.executeQuery |
Statement.execute |
Statement.executeQuery |
以上四种语言示例均实现了相同逻辑,可根据项目技术栈选择参考。
官方文档
- PostgreSQL 官方文档 - 服务器配置
- PostgreSQL 官方文档 - 资源消耗参数
- PostgreSQL 官方文档 - WAL 配置
- PostgreSQL 官方文档 - 自动清理
- PostgreSQL 官方文档 - 查询规划
- PostgreSQL 官方文档 - 常规清理与自动清理
参考链接
总结
本文围绕 PostgreSQL 基础性能调优展开,核心要点如下:
- 二八法则:聚焦 20% 的关键参数(内存、检查点、自动清理、I/O 成本),即可获得 80% 的性能收益。
- 内存参数 :
shared_buffers设为总内存 25%;effective_cache_size设为 50%~75%(非实际分配);work_mem建议在会话级别按需设置,避免全局过大导致 OOM;maintenance_work_mem按每 1GB 内存 50MB 配置。 - 检查点参数 :
checkpoint_timeout设为 15~30 分钟,checkpoint_completion_target设为 0.9 以实现平滑写入。 - 自动清理 :根据 CPU 核心数调整
autovacuum_max_workers,SSD 存储可提高autovacuum_vacuum_cost_limit。 - I/O 成本常量 :现代 SSD 环境下,将
random_page_cost从默认 4.0 降至 1.5~2.0,让优化器更准确地选择索引扫描。 - 辅助工具 :使用
pgtune或pg_configurator生成初始配置,再结合实际监控数据进行微调。 - 配置生效:PostgreSQL 以最后一次出现的参数值为准,建议将调优参数统一追加至配置文件末尾。