PostgreSQL 性能调优:从查询计划到索引策略的全链路优化
如果你从 MySQL 迁移到 PostgreSQL,最先感受到的不仅是更严格的 SQL 标准,还有更丰富的索引类型和更智能的查询优化器。但这些优势要真正发挥出来,需要正确的调优方法。
EXPLAIN ANALYZE:不只是看,还要跑
MySQL 的 EXPLAIN 只给预估,而 PostgreSQL 的 EXPLAIN ANALYZE 会实际执行查询并给出精确耗时:
1 | EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) |
关键指标:actual time(第一个数字是首行延迟,第二个是总耗时)、Buffers shared hit/read(缓存命中 vs 磁盘读取)、rows vs planned rows(差距大说明统计信息过时)。
索引策略:PostgreSQL 的独特武器
B-Tree(默认)
适用于等值查询和范围查询,90% 的场景用它就够了。
BRIN(Block Range INdex)
特别适合时序数据和日志表。BRIN 不索引每一行,而是索引每个数据块的统计摘要——体积只有 B-Tree 的千分之一:
1 | CREATE INDEX idx_logs_time ON api_logs USING BRIN (created_at) |
GIN(Generalized Inverted Index)
全文搜索和 JSONB 查询的利器:
1 | -- JSONB 索引 |
覆盖索引(INCLUDE)
PostgreSQL 11+ 支持索引包含额外列,避免回表:
1 | CREATE INDEX idx_users_covering ON users (id) INCLUDE (name, email); |
VACUUM 与 autovacuum
PostgreSQL 的 MVCC 机制会导致死元组(dead tuples)堆积。不及时清理会导致表膨胀、查询变慢甚至事务 ID 回卷。
调优 autovacuum:
1 | ALTER TABLE orders SET ( |
监控死元组:
1 | SELECT schemaname, relname, n_dead_tup, n_live_tup, |
连接池:PgBouncer 配置
PostgreSQL 每个连接都是一个独立进程(不像 MySQL 的线程模型),连接开销大。生产环境必须用连接池:
1 | [pgbouncer] |
总结
PostgreSQL 的性能调优不是照搬 MySQL 经验。EXPLAIN ANALYZE 给你精确数据,BRIN/GIN 索引解决特殊场景,VACUUM 调优是长期运行的基础,连接池是不可或缺的架构层。选对了工具组合,PG 的性能上限远超大多数人的想象。
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自CC 的技术工坊
