EXPLAIN是PostgreSQL优化查询的核心工具,通过它可以直观了解查询的执行路径(如是否使用索引、连接策略等)。建议始终使用EXPLAIN ANALYZE(不仅显示计划,还实际执行查询并收集统计信息,如实际执行时间、返回行数),重点关注以下指标:
索引是提升查询速度的关键,但需合理设计以避免过度索引(影响写性能):
WHERE id = 1)、范围查询(如WHERE date BETWEEN '2023-01-01' AND '2023-12-31')。to_tsvector列)、数组(如tags列)、JSONB数据(如data->>'name')。WHERE log_time BETWEEN '2023-07-01' AND '2023-07-31')。CREATE INDEX idx_user_order ON orders(user_id, order_date),优化WHERE user_id = 1001 AND order_date > '2023-01-01')。CREATE INDEX idx_active_users ON users(email) WHERE status = 'active',优化“查询活跃用户”的场景)。CREATE INDEX idx_lower_name ON users(lower(name)),优化WHERE lower(name) = 'john doe'的不区分大小写查询)。pg_stat_user_indexes视图监控索引使用情况(如SELECT indexrelid::regclass, idx_scan FROM pg_stat_user_indexes WHERE idx_scan = 0,找出未使用的索引并删除);使用REINDEX CONCURRENTLY(如REINDEX INDEX CONCURRENTLY idx_orders_price)避免锁表,适合生产环境。根据服务器硬件资源(内存、CPU、磁盘)调整配置,充分发挥数据库性能:
shared_buffers:设置为系统内存的25%-40%(如16GB内存设置为4GB),用于缓存数据页,减少磁盘I/O。work_mem:设置为2MB-16MB(如4MB),用于排序、哈希连接等操作的内存分配,避免磁盘临时文件。maintenance_work_mem:设置为16MB-64MB(如32MB),用于VACUUM、CREATE INDEX等维护操作,提升效率。effective_cache_size:设置为系统内存的50%-70%(如16GB内存设置为12GB),表示操作系统和PostgreSQL可用的缓存大小,帮助优化器做出更好的决策。random_page_cost:若使用SSD,将其从默认的4.0降低到1.1-2.0(SSD随机读取成本更低),让优化器更倾向于使用索引。max_parallel_workers_per_gather:设置为CPU核心数的50%-70%(如8核设置为4),允许查询使用并行工作进程,加速大表扫描、聚合等操作。编写高效的SQL语句是基础,需避免以下问题:
SELECT id, name FROM users),减少数据传输量和内存占用。WHERE status = 'active'),减少结果集大小;避免在WHERE子句中对列进行函数操作(如WHERE UPPER(name) = 'JOHN'),这会导致索引失效。ON orders.user_id = users.id,需在user_id上创建索引)。INSERT INTO ... VALUES (...), (...), ...替代多次单条插入;使用COPY命令(如COPY users FROM '/path/to/file.csv' WITH CSV)替代INSERT,大幅提升批量数据导入速度。保持数据库的健康状态,避免性能退化:
VACUUM ANALYZE(同时更新统计信息),建议对频繁更新的表设置自动VACUUM(默认开启)。ANALYZE table_name手动执行,或设置autovacuum_analyze_threshold自动触发。RANGE (order_date)、按ID范围RANGE (id)),减少查询扫描的数据量(如查询2023年的订单,只需扫描对应分区)。PostgreSQL的连接创建和销毁成本较高(如需要分配内存、初始化会话),使用连接池(如PgBouncer)可以复用连接,减少开销:
pgbouncer.ini中设置pool_mode = session(会话池,适合大多数场景)、max_client_conn = 100(最大客户端连接数)、default_pool_size = 20(每个数据库的最大连接数)。通过监控工具持续跟踪查询性能,及时发现问题:
CREATE EXTENSION pg_stat_statements;),收集查询的执行次数、总执行时间、平均执行时间等统计信息(如SELECT query, calls, total_time, mean_time FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10,找出最耗时的查询)。log_min_duration_statement参数(如设置为2000,单位毫秒)记录执行时间超过阈值的查询(如log_min_duration_statement = 2000,记录执行时间超过2秒的查询),便于后续分析。