AppForge
返回首页
后端开发PostgreSQL数据库性能优化

PostgreSQL 查询优化:从慢查询到高性能

深入分析 PostgreSQL 查询执行计划,学习索引优化、查询重写等实用技巧。

B
Bruce
全栈开发工程师,热爱技术分享
2024-12-259 分钟

分析查询性能


使用 EXPLAIN ANALYZE 分析查询执行计划:


EXPLAIN ANALYZE

SELECT * FROM orders

WHERE user_id = 123

AND created_at > '2024-01-01';


索引优化


创建合适的索引


-- 单列索引

CREATE INDEX idx_orders_user_id ON orders(user_id);


-- 复合索引(注意列顺序)

CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);


-- 部分索引

CREATE INDEX idx_orders_pending ON orders(status)

WHERE status = 'pending';


-- 表达式索引

CREATE INDEX idx_users_email_lower ON users(LOWER(email));


索引使用原则


  • **选择性高的列优先**:唯一值越多,索引效果越好
  • **复合索引列顺序**:等值查询的列放前面,范围查询的列放后面
  • **避免过多索引**:索引会增加写入开销

  • 查询重写


    避免 SELECT *


    -- ❌ 不推荐

    SELECT * FROM orders WHERE user_id = 123;


    -- ✅ 推荐

    SELECT id, status, total FROM orders WHERE user_id = 123;


    使用 EXISTS 替代 IN


    -- ❌ 子查询可能很慢

    SELECT * FROM orders

    WHERE user_id IN (SELECT id FROM users WHERE status = 'active');


    -- ✅ EXISTS 通常更快

    SELECT * FROM orders o

    WHERE EXISTS (

    SELECT 1 FROM users u

    WHERE u.id = o.user_id AND u.status = 'active'

    );


    分页优化


    -- ❌ OFFSET 大时性能差

    SELECT * FROM orders ORDER BY id LIMIT 20 OFFSET 10000;


    -- ✅ 使用游标分页

    SELECT * FROM orders

    WHERE id > 10000

    ORDER BY id

    LIMIT 20;


    连接优化


    -- 确保连接列有索引

    CREATE INDEX idx_order_items_order_id ON order_items(order_id);


    -- 使用合适的连接类型

    SELECT o.*, oi.*

    FROM orders o

    INNER JOIN order_items oi ON o.id = oi.order_id

    WHERE o.user_id = 123;


    配置优化


    -- 查看当前配置

    SHOW shared_buffers;

    SHOW work_mem;

    SHOW effective_cache_size;


    -- 推荐配置(根据服务器内存调整)

    -- shared_buffers = 25% of RAM

    -- work_mem = 64MB (for complex queries)

    -- effective_cache_size = 75% of RAM


    监控慢查询


    -- 启用慢查询日志

    ALTER SYSTEM SET log_min_duration_statement = '1000'; -- 1秒


    -- 查看当前运行的查询

    SELECT pid, now() - pg_stat_activity.query_start AS duration, query

    FROM pg_stat_activity

    WHERE state = 'active'

    ORDER BY duration DESC;


    总结


    PostgreSQL 性能优化是一个持续的过程。通过分析执行计划、创建合适的索引、重写低效查询,可以显著提升数据库性能。


    B

    Bruce

    全栈开发工程师,热爱技术分享

    感谢阅读!如果这篇文章对你有帮助,欢迎分享给更多的朋友。