PostgreSQL 查询优化

2026-06-22 · 6 阅读 · 301字
PostgreSQL性能优化数据库

PostgreSQL 查询优化

使用 EXPLAIN 分析执行计划

EXPLAIN ANALYZE 是查询优化的起点,它展示 PostgreSQL 执行查询的详细步骤:

EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'pending';

输出解读重点关注:

  • 顺序扫描(Seq Scan) vs 索引扫描(Index Scan)
  • 估算行数与实际行数的偏差(反映统计信息是否准确)
  • 各步骤的实际执行时间

索引优化

B-Tree 索引

最常用的索引类型,支持等值查询和范围查询:

CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_created_at ON orders(created_at);

复合索引

对多个列的查询条件建立复合索引,注意列顺序(最左前缀原则):

CREATE INDEX idx_orders_status_created ON orders(status, created_at);

查询 WHERE status = 'pending' ORDER BY created_at 可充分利用该索引。

部分索引

只对满足条件的数据建立索引,减少索引体积:

CREATE INDEX idx_active_orders ON orders(created_at) WHERE status = 'active';

覆盖索引

通过包含所有需要字段的索引,避免回表查询:

CREATE INDEX idx_orders_covering ON orders(status) INCLUDE (id, total_amount);

查询优化技巧

避免 SELECT *

只查询需要的列,减少 I/O 和网络传输:

-- 不推荐
SELECT * FROM users;

-- 推荐
SELECT id, name, email FROM users;

使用 JOIN 而非子查询

PostgreSQL 对 JOIN 的优化通常优于子查询:

-- 子查询版本
SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 'active');

-- JOIN 版本
SELECT orders.* FROM orders JOIN users ON orders.user_id = users.id WHERE users.status = 'active';

合理使用 LIMIT

使用 LIMIT 强制查询在取得足够结果后停止扫描:

SELECT * FROM products ORDER BY created_at DESC LIMIT 20;

统计信息维护

保持统计信息的准确性对查询优化器至关重要:

ANALYZE orders;                     -- 更新统计信息
SET default_statistics_target = 100; -- 提高统计精度(全局)
ALTER TABLE orders ALTER COLUMN status SET STATISTICS 200; -- 针对特定列

配置调优

参数 说明 推荐值
shared_buffers 共享缓冲区大小 内存的 25%
work_mem 排序/哈希操作内存 根据查询复杂度调整
effective_cache_size 操作系统缓存估算 内存的 50%-75%
random_page_cost 随机 I/O 成本 SSD 设为 1.1

分区表

对于大表,使用分区提升查询和维护性能:

CREATE TABLE orders (
    id BIGSERIAL,
    created_at TIMESTAMPTZ,
    data JSONB
) PARTITION BY RANGE (created_at);

CREATE TABLE orders_2024_01 PARTITION OF orders
    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');

CREATE TABLE orders_2024_02 PARTITION OF orders
    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');