PostgreSQL教程FG308-PostgreSQL性能优化
本文档风哥主要介绍PostgreSQL性能优化,包括服务器参数优化、查询优化、索引优化等内容。风哥教程参考PostgreSQL官方文档Server Administration部分,适合DBA人员在生产环境中使用。
Part01-基础概念与理论知识
1.1 PostgreSQL性能优化概述
PostgreSQL性能优化是指通过各种技术手段,提高数据库系统的性能,包括响应速度、吞吐量和资源利用率等。性能优化是数据库运维的重要任务之一,关系到系统的稳定性和用户体验。
- 提高用户体验:减少查询响应时间
- 提高系统吞吐量:处理更多并发请求
- 降低资源消耗:减少CPU、内存和存储使用
- 提高系统稳定性:避免性能瓶颈导致的系统崩溃
- 降低运维成本:减少硬件和人力资源投入
1.2 PostgreSQL性能指标
PostgreSQL性能指标主要包括以下几个方面:
- 响应时间:查询执行时间,包括客户端等待时间和服务器处理时间
- 吞吐量:单位时间内处理的查询数量
- 并发连接数:同时连接到数据库的客户端数量
- 资源利用率:CPU、内存、磁盘I/O等资源的使用情况
- 缓存命中率:缓冲区缓存的命中率
- 锁竞争:锁等待和锁冲突的情况
1.3 PostgreSQL性能瓶颈
PostgreSQL性能瓶颈主要包括以下几个方面:
1. 硬件瓶颈:CPU、内存、磁盘I/O、网络带宽等
2. 配置瓶颈:PostgreSQL参数配置不合理
3. 查询瓶颈:SQL语句执行效率低
4. 索引瓶颈:索引设计不合理或缺失
5. 锁瓶颈:锁竞争导致的性能下降
6. 存储瓶颈:存储系统性能不足
7. 连接瓶颈:连接数过多或连接池配置不合理
Part02-生产环境规划与建议
2.1 性能规划
在生产环境中,合理的性能规划是确保系统性能的关键:
1. 明确性能目标:确定系统的性能指标和目标值
2. 分析工作负载:了解系统的查询模式和数据访问模式
3. 评估资源需求:根据工作负载评估所需的硬件资源
4. 制定优化策略:根据性能目标和资源情况制定优化策略
5. 建立监控体系:建立性能监控系统,及时发现问题
6. 定期评估:定期评估系统性能,调整优化策略
# 性能规划示例
– 响应时间目标:95%的查询响应时间小于100ms
– 吞吐量目标:每秒处理1000个查询
– 并发连接数:支持1000个并发连接
– 资源配置:8核CPU、16GB内存、SSD存储
2.2 性能需求分析
性能需求分析应包括以下内容:
- 业务需求:了解业务对性能的要求
- 数据量:评估数据量大小和增长趋势
- 查询模式:分析查询类型和频率
- 并发用户:评估并发用户数量和增长趋势
- 峰值负载:分析系统的峰值负载情况
2.3 性能调优策略
性能调优策略应考虑以下因素:
1. 硬件优化:选择合适的硬件配置
2. 配置优化:调整PostgreSQL参数
3. 查询优化:优化SQL语句
4. 索引优化:设计合理的索引
5. 存储优化:优化存储系统
6. 连接管理:合理管理数据库连接
7. 监控与分析:建立性能监控系统
# 性能调优步骤
1. 性能基准测试:建立性能基准
2. 性能分析:识别性能瓶颈
3. 优化实施:实施优化措施
4. 性能验证:验证优化效果
5. 持续监控:持续监控系统性能
Part03-生产环境项目实施方案
3.1 服务器参数优化
3.1.1 内存参数优化
$ sudo vi /postgresql/fgdata/postgresql.conf
# 共享内存
shared_buffers = 4GB # 建议设置为系统内存的25%
# 工作内存
work_mem = 32MB # 根据并发查询数量和系统内存调整
# 维护工作内存
maintenance_work_mem = 1GB # 建议设置为系统内存的10%
# 自动清理工作内存
autovacuum_work_mem = 256MB
# 重启PostgreSQL
$ sudo systemctl restart postgresql
# 验证内存参数
$ psql -U fgedu -d fgedudb -c “SHOW shared_buffers;”
shared_buffers
—————-
4GB
$ psql -U fgedu -d fgedudb -c “SHOW work_mem;”
work_mem
———-
32MB
3.1.2 连接参数优化
$ sudo vi /postgresql/fgdata/postgresql.conf
# 最大连接数
max_connections = 1000
# 连接池设置
# 使用PgBouncer或PgPool-II进行连接池管理
# 重启PostgreSQL
$ sudo systemctl restart postgresql
# 验证连接参数
$ psql -U fgedu -d fgedudb -c “SHOW max_connections;”
max_connections
—————–
1000
3.1.3 写入性能参数优化
$ sudo vi /postgresql/fgdata/postgresql.conf
# WAL缓冲区
wal_buffers = 16MB # 建议设置为16MB-64MB
# 同步提交
synchronous_commit = on # 风哥教程针对风哥教程针对风哥教程针对生产环境建议开启
# 提交延迟
commit_delay = 0
commit_siblings = 5
# 预写式日志级别
wal_level = replica # 支持复制
# 重启PostgreSQL
$ sudo systemctl restart postgresql
# 验证写入性能参数
$ psql -U fgedu -d fgedudb -c “SHOW wal_buffers;”
wal_buffers
————-
16MB
$ psql -U fgedu -d fgedudb -c “SHOW synchronous_commit;”
synchronous_commit
——————–
on
3.2 查询优化
3.2.1 查看执行计划
$ psql -U fgedu -d fgedudb -c “EXPLAIN ANALYZE SELECT * FROM fgedu_users WHERE email = ‘test@fgedu.net.cn’;”
# 输出示例
Nested Loop (cost=0.29..8.31 rows=1 width=44) (actual time=0.027..0.028 rows=1 loops=1)
-> Index Scan using fgedu_users_email_idx on fgedu_users (cost=0.29..4.30 rows=1 width=44) (actual
time=0.020..0.021 rows=1 loops=1)
Index Cond: (email = ‘test@fgedu.net.cn’::text)
-> Seq Scan on fgedu_users (cost=0.00..4.01 rows=1 width=44) (actual time=0.006..0.006 rows=1 loops=1)
Filter: (email = ‘test@fgedu.net.cn’::text)
Rows Removed by Filter: 999
Planning Time: 0.084 ms
Execution Time: 0.045 ms
3.2.2 优化查询语句
SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;
# 优化后的查询
SELECT id, name, email FROM fgedu_users WHERE name LIKE ‘%test%’;
# 优化前的执行计划
Seq Scan on fgedu_users (cost=0.00..4.01 rows=10 width=44) (actual time=0.015..0.015 rows=10 loops=1)
Filter: (name ~~ ‘%test%’::text)
Rows Removed by Filter: 990
Planning Time: 0.052 ms
Execution Time: 0.023 ms
# 优化后的执行计划
Seq Scan on fgedu_users (cost=0.00..4.01 rows=10 width=36) (actual time=0.012..0.012 rows=10 loops=1)
Filter: (name ~~ ‘%test%’::text)
Rows Removed by Filter: 990
Planning Time: 0.048 ms
Execution Time: 0.019 ms
3.3 索引优化
3.3.1 创建合适的索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_users_email_idx ON fgedu_users(email);”
# 创建复合索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_users_name_email_idx ON fgedu_users(name, email);”
# 创建部分索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_users_active_idx ON fgedu_users(id) WHERE active = true;”
# 验证索引
$ psql -U fgedu -d fgedudb -c “\d fgedu_users”
# 查看索引使用情况
$ psql -U fgedu -d fgedudb -c “SELECT * FROM pg_stat_user_indexes WHERE schemaname = ‘public’;”
Part04-生产案例与实战讲解
4.1 服务器参数优化案例
4.1.1 生产环境服务器参数优化
# 编辑postgresql.conf文件
$ sudo vi /postgresql/fgdata/postgresql.conf
# 内存参数
shared_buffers = 8GB
work_mem = 64MB
maintenance_work_mem = 2GB
autovacuum_work_mem = 512MB
# 连接参数
max_connections = 1000
# 写入性能参数
wal_buffers = 64MB
synchronous_commit = on
commit_delay = 0
commit_siblings = 5
# 查询优化参数
effective_cache_size = 24GB
random_page_cost = 1.1
seq_page_cost = 1.0
# 自动清理参数
autovacuum = on
autovacuum_max_workers = 4
autovacuum_naptime = 10s
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.025
# 重启PostgreSQL
$ sudo systemctl restart postgresql
# 验证参数配置
$ psql -U fgedu -d fgedudb -c “SHOW shared_buffers;”
shared_buffers
—————-
8GB
$ psql -U fgedu -d fgedudb -c “SHOW work_mem;”
work_mem
———-
64MB
$ psql -U fgedu -d fgedudb -c “SHOW effective_cache_size;”
effective_cache_size
———————-
24GB
4.2 查询优化案例
4.2.1 复杂查询优化
SELECT
u.id, u.name, u.email,
COUNT(o.id) as order_count,
SUM(o.amount) as total_amount
FROM
fgedu_users u
LEFT JOIN
fgedu_orders o ON u.id = o.user_id
WHERE
u.active = true
GROUP BY
u.id, u.name, u.email
ORDER BY
total_amount DESC
LIMIT 10;
# 优化后的查询
SELECT
u.id, u.name, u.email,
COALESCE(order_stats.order_count, 0) as order_count,
COALESCE(order_stats.total_amount, 0) as total_amount
FROM
fgedu_users u
LEFT JOIN (
SELECT
user_id,
COUNT(*) as order_count,
SUM(amount) as total_amount
FROM
fgedu_orders
GROUP BY
user_id
) as order_stats ON u.id = order_stats.user_id
WHERE
u.active = true
ORDER BY
total_amount DESC
LIMIT 10;
# 执行计划对比
# 优化前
HashAggregate (cost=23.01..25.01 rows=100 width=56) (actual time=0.123..0.124 rows=10 loops=1)
Group Key: u.id, u.name, u.email
-> Hash Left Join (cost=8.01..18.01 rows=1000 width=28) (actual time=0.034..0.076 rows=1000 loops=1)
Hash Cond: (u.id = o.user_id)
-> Seq Scan on fgedu_users u (cost=0.00..4.01 rows=100 width=20) (actual time=0.010..0.015 rows=100 loops=1)
Filter: active
Rows Removed by Filter: 900
-> Hash (cost=4.01..4.01 rows=1000 width=12) (actual time=0.018..0.018 rows=1000 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 44kB
-> Seq Scan on fgedu_orders o (cost=0.00..4.01 rows=1000 width=12) (actual time=0.006..0.009 rows=1000
loops=1)
Planning Time: 0.123 ms
Execution Time: 0.145 ms
# 优化后
Hash Left Join (cost=12.02..16.02 rows=100 width=56) (actual time=0.067..0.070 rows=10 loops=1)
Hash Cond: (u.id = order_stats.user_id)
-> Seq Scan on fgedu_users u (cost=0.00..4.01 rows=100 width=20) (actual time=0.011..0.016 rows=100 loops=1)
Filter: active
Rows Removed by Filter: 900
-> Hash (cost=8.01..8.01 rows=100 width=40) (actual time=0.048..0.048 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 12kB
-> HashAggregate (cost=4.01..8.01 rows=100 width=40) (actual time=0.036..0.041 rows=100 loops=1)
Group Key: o.user_id
-> Seq Scan on fgedu_orders o (cost=0.00..4.01 rows=1000 width=12) (actual time=0.007..0.009 rows=1000
loops=1)
Planning Time: 0.156 ms
Execution Time: 0.092 ms
4.3 索引优化案例
4.3.1 索引设计与优化
# 1. 分析查询模式
$ psql -U fgedu -d fgedudb -c “SELECT * FROM pg_stat_user_tables WHERE schemaname = ‘public’;”
# 2. 识别频繁查询的列
$ psql -U fgedu -d fgedudb -c “SELECT * FROM pg_stat_user_indexes WHERE schemaname = ‘public’;”
# 3. 创建合适的索引
# 为频繁查询的列创建索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_orders_user_id_idx ON fgedu_orders(user_id);”
# 为复合查询创建复合索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_orders_user_id_created_at_idx ON fgedu_orders(user_id,
created_at);”
# 为范围查询创建索引
$ psql -U fgedu -d fgedudb -c “CREATE INDEX fgedu_orders_created_at_idx ON fgedu_orders(created_at);”
# 4. 验证索引使用情况
$ psql -U fgedu -d fgedudb -c “EXPLAIN ANALYZE SELECT * FROM fgedu_orders WHERE user_id = 1 AND created_at >
‘2026-04-01’;”
# 输出示例
Index Scan using fgedu_orders_user_id_created_at_idx on fgedu_orders (cost=0.29..8.31 rows=10 width=28)
(actual time=0.020..0.021 rows=10 loops=1)
Index Cond: ((user_id = 1) AND (created_at > ‘2026-04-01’::date))
Planning Time: 0.084 ms
Execution Time: 0.032 ms
# 5. 清理无用索引
$ psql -U fgedu -d fgedudb -c “DROP INDEX IF EXISTS fgedu_orders_old_idx;”
Part05-风哥经验总结与分享
5.1 性能优化最佳实践
PostgreSQL性能优化的最佳实践:
- 硬件选型:选择合适的硬件配置,包括CPU、内存、存储和网络
- 参数调优:根据系统特点调整PostgreSQL参数
- 查询优化:优化SQL语句,减少不必要的操作
- 索引设计:创建合适的索引,提高查询速度
- 存储优化:使用高性能存储设备,优化存储配置
- 连接管理:使用连接池,合理管理数据库连接
- 监控与分析:建立性能监控系统,及时发现和解决问题
- 定期维护:定期进行VACUUM和ANALYZE操作,保持系统性能
5.2 风哥经验分享
1. 性能优化要全面:从硬件、配置、查询、索引等多个方面进行优化
2. 性能基准要建立:建立性能基准,便于比较优化效果
3. 监控系统要完善:建立实时监控系统,及时发现性能问题
4. 优化策略要针对性:根据具体的性能瓶颈制定优化策略
5. 测试验证要充分:充分测试优化效果,确保优化措施有效
6. 持续优化要坚持:性能优化是一个持续的过程,需要不断调整和改进
通过合理的性能优化,可以显著提高系统的性能和稳定性,为业务提供更好的支持。from PostgreSQL视频:www.itpux.com
5.3 常见问题与解决方案
PostgreSQL性能优化常见问题与解决方案:
症状:查询执行时间过长
解决方案:
– 分析执行计划,找出性能瓶颈
– 创建合适的索引
– 优化SQL语句
– 调整服务器参数
# 常见问题2:系统负载过高
症状:CPU、内存或磁盘I/O使用率过高
解决方案:
– 分析系统负载来源
– 优化查询,减少资源消耗
– 调整服务器参数
– 考虑升级硬件
# 常见问题3:连接数过多
症状:数据库连接数达到上限
解决方案:
– 使用连接池管理连接
– 调整max_connections参数
– 优化应用程序连接管理
– 监控并关闭空闲连接
# 常见问题4:索引失效
症状:索引未被使用
解决方案:
– 分析查询计划,确认索引是否被使用
– 检查索引是否适合查询模式
– 重建索引
– 运行ANALYZE更新统计信息
# 常见问题5:自动清理不及时
症状:表膨胀,性能下降
解决方案:
– 调整autovacuum参数
– 手动运行VACUUM和ANALYZE
– 监控表膨胀情况
– 考虑使用pg_repack等工具
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
