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_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秒的查詢),便于后續分析。