PostgreSQL教程FG225-PG查询优化器:原理与实践
本文档风哥主要介绍PostgreSQL数据库的查询优化器,包括查询优化器的原理、配置、调优等内容,风哥教程参考PostgreSQL官方文档Query Optimization内容,适合数据库管理员和开发者在学习和测试中使用。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 PostgreSQL查询优化器概念
查询优化器是PostgreSQL数据库的核心组件之一,它负责分析SQL语句,生成最优的执行计划,以最小的代价执行查询。查询优化器通过考虑各种执行路径,选择最佳的执行计划,提高查询性能。
- 基于成本:使用成本模型选择执行计划
- 基于规则:使用规则指导执行计划生成
- 动态规划:考虑所有可能的执行路径
- 统计信息:使用表和索引的统计信息
- 并行查询:支持并行执行查询
1.2 PostgreSQL查询优化器原理
PostgreSQL查询优化器的工作原理:
- 解析:将SQL语句解析为语法树
- 重写:对语法树进行重写,优化查询结构
- 规划:生成多个可能的执行计划
- 成本估算:估算每个执行计划的成本
- 选择:选择成本最低的执行计划
- 执行:执行选定的执行计划
1.3 PostgreSQL查询优化器优势
PostgreSQL查询优化器的优势:
- 提高查询性能:选择最优的执行计划
- 减少资源消耗:最小化CPU、内存和IO使用
- 适应数据变化:根据统计信息调整执行计划
- 支持复杂查询:处理复杂的SQL语句
- 并行执行:利用多核CPU提高性能
Part02-生产环境规划与建议
2.1 PostgreSQL查询优化器配置
PostgreSQL查询优化器配置建议:
# 统计信息
autovacuum_analyze_scale_factor = 0.05 # 自动分析比例因子
autovacuum_analyze_threshold = 50 # 自动分析阈值
# 规划器参数
random_page_cost = 4.0 # 随机页面成本
seq_page_cost = 1.0 # 顺序页面成本
cpu_tuple_cost = 0.01 # CPU元组成本
cpu_index_tuple_cost = 0.005 # CPU索引元组成本
cpu_operator_cost = 0.0025 # CPU操作符成本
effective_cache_size = 4GB # 有效缓存大小
# 并行查询
max_parallel_workers_per_gather = 2 # 每个Gather节点的最大并行工作线程数
max_parallel_workers = 8 # 系统的最大并行工作线程数
# 示例:修改查询优化器配置
ALTER SYSTEM SET random_page_cost = ‘1.1’; # SSD存储
ALTER SYSTEM SET effective_cache_size = ‘8GB’;
ALTER SYSTEM SET max_parallel_workers_per_gather = ‘4’;
SELECT pg_reload_conf();
2.2 PostgreSQL查询优化器性能优化
PostgreSQL查询优化器性能优化建议:
# 统计信息优化
– 定期执行ANALYZE
– 调整autovacuum参数
– 使用扩展统计信息
# 索引优化
– 创建合适的索引
– 避免过度索引
– 定期维护索引
# 查询优化
– 优化SQL语句
– 使用合适的连接方式
– 避免全表扫描
# 内存优化
– 调整work_mem
– 调整shared_buffers
– 调整maintenance_work_mem
# 示例:查询优化器性能优化
— 定期执行ANALYZE
ANALYZE fgedu_fgedus;
— 创建合适的索引
CREATE INDEX idx_fgedu_fgedus_email ON fgedu_fgedus(email);
— 优化SQL语句
— 优化前
SELECT * FROM fgedu_fgedus WHERE email LIKE ‘%fgedu.net.cn’;
— 优化后
SELECT id, fgeduname, email FROM fgedu_fgedus WHERE email LIKE ‘%fgedu.net.cn’;
2.3 PostgreSQL查询优化器监控
PostgreSQL查询优化器监控建议:
- 执行计划:监控查询执行计划
- 统计信息:监控表和索引的统计信息
- 性能指标:监控查询执行时间和资源使用
- 慢查询:监控慢查询
- 规划时间:监控查询规划时间
Part03-生产环境项目实施方案
3.1 PostgreSQL查询优化器实施
3.1.1 统计信息实施
# 步骤1:修改统计信息配置
ALTER SYSTEM SET autovacuum_analyze_scale_factor = ‘0.05’;
ALTER SYSTEM SET autovacuum_analyze_threshold = ’50’;
SELECT pg_reload_conf();
# 步骤2:手动执行ANALYZE
ANALYZE fgedu_fgedus;
ANALYZE fgedu_orders;
# 步骤3:查看统计信息
SELECT
relname,
n_live_tup,
n_dead_tup,
last_analyze,
last_autoanalyze
FROM pg_stat_fgedu_tables
WHERE relname LIKE ‘fgedu_%’;
# 结果示例
-[ RECORD 1 ]——+————————
relname | fgedu_fgedus
n_live_tup | 1000
n_dead_tup | 100
last_analyze | 2024-01-01 12:00:00
last_autoanalyze | 2024-01-01 11:00:00
# 步骤4:使用扩展统计信息
CREATE STATISTICS fgedu_fgedus_stats (dependencies) ON fgeduname, email FROM fgedu_fgedus;
ANALYZE fgedu_fgedus;
3.1.2 索引实施
# 步骤1:分析查询
EXPLAIN ANALYZE SELECT * FROM fgedu_fgedus WHERE email = ‘fgedu@fgedu.net.cn’;
# 步骤2:创建索引
CREATE INDEX idx_fgedu_fgedus_email ON fgedu_fgedus(email);
# 步骤3:验证索引使用
EXPLAIN ANALYZE SELECT * FROM fgedu_fgedus WHERE email = ‘fgedu@fgedu.net.cn’;
# 结果示例
QUERY PLAN
——————————————————————–
Bitmap Heap Scan on fgedu_fgedus (cost=4.29..14.58 rows=1 width=100)
Recheck Cond: (email = ‘fgedu@fgedu.net.cn’)
-> Bitmap Index Scan on idx_fgedu_fgedus_email (cost=0.00..4.29 rows=1 width=0)
Index Cond: (email = ‘fgedu@fgedu.net.cn’)
Planning Time: 0.103 ms
Execution Time: 0.234 ms
# 步骤4:维护索引
REINDEX INDEX idx_fgedu_fgedus_email;
3.2 PostgreSQL查询优化器策略
3.2.1 索引策略
# 策略1:选择合适的索引类型
– B-tree:适用于等值查询和范围查询
– Hash:适用于等值查询
– GiST:适用于几何数据和全文搜索
– GIN:适用于数组和JSONB
– BRIN:适用于大型表的范围查询
# 策略2:创建复合索引
– 考虑查询条件的顺序
– 前缀匹配原则
– 避免过多的列
# 策略3:使用部分索引
– 只索引常用的行
– 减少索引大小
– 提高查询性能
# 示例:索引策略
— 创建B-tree索引
CREATE INDEX idx_fgedu_fgedus_email ON fgedu_fgedus(email);
— 创建复合索引
CREATE INDEX idx_fgedu_orders_customer_date ON fgedu_orders(customer_id, order_date);
— 创建部分索引
CREATE INDEX idx_fgedu_fgedus_active ON fgedu_fgedus(email) WHERE active = true;
3.2.2 查询策略
# 策略1:优化WHERE子句
– 使用索引列
– 避免使用函数
– 避免使用LIKE ‘%…’
# 策略2:优化JOIN操作
– 使用合适的连接类型
– 小表驱动大表
– 使用索引连接
# 策略3:优化聚合操作
– 使用索引
– 考虑部分聚合
– 避免不必要的聚合
# 示例:查询策略
— 优化WHERE子句
— 优化前
SELECT * FROM fgedu_fgedus WHERE LOWER(email) = ‘fgedu@fgedu.net.cn’;
— 优化后
SELECT * FROM fgedu_fgedus WHERE email = ‘fgedu@fgedu.net.cn’;
— 优化JOIN操作
— 优化前
SELECT * FROM fgedu_orders o JOIN fgedu_fgedus u ON o.customer_id = u.id;
— 优化后
SELECT o.order_id, o.amount, u.fgeduname FROM fgedu_orders o JOIN fgedu_fgedus u ON o.customer_id = u.id;
3.3 PostgreSQL查询优化器调优
3.3.1 成本参数调优
# 存储类型调优
– HDD:random_page_cost = 4.0
– SSD:random_page_cost = 1.1
– 内存:random_page_cost = 1.0
# CPU调优
– cpu_tuple_cost:CPU处理每个元组的成本
– cpu_index_tuple_cost:CPU处理每个索引元组的成本
– cpu_operator_cost:CPU处理每个操作符的成本
# 缓存调优
effective_cache_size:系统可用的缓存大小
# 示例:成本参数调优
— SSD存储
ALTER SYSTEM SET random_page_cost = ‘1.1’;
— 调整缓存大小
ALTER SYSTEM SET effective_cache_size = ‘8GB’;
— 调整CPU成本
ALTER SYSTEM SET cpu_tuple_cost = ‘0.01’;
ALTER SYSTEM SET cpu_index_tuple_cost = ‘0.005’;
ALTER SYSTEM SET cpu_operator_cost = ‘0.0025’;
SELECT pg_reload_conf();
3.3.2 并行查询调优
# 并行度调优
max_parallel_workers_per_gather:每个Gather节点的最大并行工作线程数
max_parallel_workers:系统的最大并行工作线程数
max_parallel_maintenance_workers:维护操作的最大并行工作线程数
# 表级并行
ALTER TABLE fgedu_fgedus SET (parallel_workers = 4);
# 示例:并行查询调优
— 调整并行度
ALTER SYSTEM SET max_parallel_workers_per_gather = ‘4’;
ALTER SYSTEM SET max_parallel_workers = ‘8’;
— 启用表级并行
ALTER TABLE fgedu_fgedus SET (parallel_workers = 4);
— 测试并行查询
EXPLAIN ANALYZE SELECT * FROM fgedu_fgedus WHERE age > 30;
# 结果示例
QUERY PLAN
——————————————————————–
Gather (cost=1000.00..1234.56 rows=1000 width=100)
Workers Planned: 4
Workers Launched: 4
-> Parallel Seq Scan on fgedu_fgedus (cost=0.00..1134.56 rows=250 width=100)
Filter: (age > 30)
Rows Removed by Filter: 750
Planning Time: 0.103 ms
Execution Time: 5.234 ms
Part04-生产案例与实战讲解
4.1 PostgreSQL查询优化器实战案例
4.1.1 慢查询优化案例
# 场景:电商网站订单查询
# 优化前
– 查询时间:5秒
– 执行计划:全表扫描
– 索引:无
# 优化后
– 查询时间:0.1秒
– 执行计划:索引扫描
– 索引:创建复合索引
# 优化步骤
1. 分析慢查询
2. 创建合适的索引
3. 优化SQL语句
4. 调整查询优化器参数
# 示例:慢查询优化
— 慢查询
SELECT * FROM fgedu_orders WHERE customer_id = 1 AND order_date >= ‘2024-01-01’;
— 分析执行计划
EXPLAIN ANALYZE SELECT * FROM fgedu_orders WHERE customer_id = 1 AND order_date >= ‘2024-01-01’;
— 创建索引
CREATE INDEX idx_fgedu_orders_customer_date ON fgedu_orders(customer_id, order_date);
— 优化后查询
EXPLAIN ANALYZE SELECT order_id, amount, order_date FROM fgedu_orders WHERE customer_id = 1 AND order_date >= ‘2024-01-01’;
# 结果示例
QUERY PLAN
——————————————————————–
Index Scan using idx_fgedu_orders_customer_date on fgedu_orders (cost=0.29..8.31 rows=10 width=20)
Index Cond: (customer_id = 1 AND order_date >= ‘2024-01-01’::date)
Planning Time: 0.103 ms
Execution Time: 0.123 ms
4.2 PostgreSQL查询优化器工具使用
4.2.1 使用EXPLAIN ANALYZE分析执行计划
# 基本用法
EXPLAIN ANALYZE SELECT * FROM fgedu_fgedus WHERE id = 1;
# 结果示例
QUERY PLAN
——————————————————————–
Index Scan using fgedu_fgedus_pkey on fgedu_fgedus (cost=0.29..8.31 rows=1 width=100)
Index Cond: (id = 1)
Planning Time: 0.103 ms
Execution Time: 0.123 ms
# 分析复杂查询
EXPLAIN ANALYZE SELECT o.order_id, o.amount, u.fgeduname
FROM fgedu_orders o
JOIN fgedu_fgedus u ON o.customer_id = u.id
WHERE o.order_date >= ‘2024-01-01’;
# 结果示例
QUERY PLAN
——————————————————————–
Hash Join (cost=10.84..25.96 rows=100 width=30)
Hash Cond: (o.customer_id = u.id)
-> Seq Scan on fgedu_orders o (cost=0.00..14.00 rows=100 width=16)
Filter: (order_date >= ‘2024-01-01’::date)
-> Hash (cost=8.00..8.00 rows=200 width=18)
-> Seq Scan on fgedu_fgedus u (cost=0.00..8.00 rows=200 width=18)
Planning Time: 0.123 ms
Execution Time: 0.234 ms
4.3 PostgreSQL查询优化器常见问题
PostgreSQL查询优化器常见问题及解决方法:
# 症状:执行计划选择不当
# 解决方法
– 执行ANALYZE
ANALYZE fgedu_fgedus;
– 调整autovacuum参数
ALTER SYSTEM SET autovacuum_analyze_scale_factor = ‘0.05’;
# 常见问题2:索引未使用
# 症状:查询使用全表扫描而不是索引扫描
# 解决方法
– 检查索引是否存在
– 检查查询条件是否使用索引列
– 检查统计信息是否更新
– 强制使用索引(不推荐)
# 常见问题3:参数化查询性能差
# 症状:参数化查询执行计划不佳
# 解决方法
– 使用prepared statements
– 考虑使用PL/pgSQL
– 调整计划缓存
# 常见问题4:并行查询性能差
# 症状:并行查询速度慢
# 解决方法
– 调整并行度参数
– 检查表级并行设置
– 考虑数据分布
# 常见问题5:查询规划时间长
# 症状:复杂查询规划时间过长
# 解决方法
– 简化查询
– 调整规划器参数
– 考虑使用物化视图
Part05-风哥经验总结与分享
5.1 PostgreSQL查询优化器最佳实践
PostgreSQL查询优化器最佳实践:
- 定期更新统计信息:确保查询优化器有准确的统计信息
- 创建合适的索引:根据查询模式创建索引
- 优化SQL语句:编写高效的SQL语句
- 调整成本参数:根据硬件环境调整成本参数
- 使用并行查询:利用多核CPU提高性能
- 监控查询性能:及时发现和解决性能问题
- 合理使用物化视图:提高复杂查询性能
- 避免过度优化:根据实际需求进行优化
5.2 PostgreSQL查询优化器检查清单
– [ ] 统计信息是否最新
– [ ] 索引是否合适
– [ ] SQL语句是否优化
– [ ] 成本参数是否调整
– [ ] 并行查询是否启用
– [ ] 慢查询是否监控
– [ ] 执行计划是否合理
– [ ] 内存配置是否优化
# 查询优化器维护清单
– [ ] 每日:监控慢查询
– [ ] 每周:执行ANALYZE
– [ ] 每月:优化索引
– [ ] 每季度:调整查询优化器参数
– [ ] 每年:评估查询优化策略
– [ ] 定期:分析执行计划
5.3 PostgreSQL查询优化器工具推荐
PostgreSQL查询优化器工具推荐:
- EXPLAIN ANALYZE:分析执行计划
- pg_stat_statements:统计SQL执行信息
- pg_stat_fgedu_tables:查看表统计信息
- pg_stat_fgedu_indexes:查看索引统计信息
- pg_show_plans:查看正在执行的查询计划
- auto_explain:自动记录执行计划
- pgBadger:日志分析工具
- pganalyze:性能分析工具
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
