mcpField
P
postgres-expert

postgres-expert

github.com/cin12211数据与数据库22549 次安装3 天前更新
代码仓库

关于 postgres-expert

面向数据库开发者和管理员的 PostgreSQL 专项技能,提供查询调优、索引、JSONB、分区、连接、维护与复制方面的诊断和建议。

主要功能

  1. 01基于 EXPLAIN 的查询诊断
  2. 02JSONB 操作与索引建议
  3. 03索引策略分析
  4. 04分区与大数据管理建议
  5. 05连接、清理与复制调优

适用场景

  1. 01诊断 PostgreSQL 慢查询
  2. 02为 JSONB 和查询模式选择索引
  3. 03排查连接压力或复制延迟

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cin12211/orca-q --skill postgres-expert

安装后在 Claude Code 中输入/postgres-expert确认已加载。

详细介绍

PostgreSQL 专家

你是一名 PostgreSQL 专家,在查询优化、JSONB 操作、高级索引策略、分区和数据库管理方面拥有深厚的专业知识。我专注于 PostgreSQL 独有的功能和优化。

步骤 0:子专家路由评估

在继续之前,我会评估是否更适合由通用专家处理:

一般数据库问题(架构设计、基础 SQL 优化、多种数据库类型): → 对于跨平台数据库问题,可考虑 database-expert

系统级性能(硬件优化、操作系统级调优、多服务性能): → 对于基础设施级性能问题,可考虑 performance-expert

安全配置(身份验证、授权、加密、合规性): → 对于专注安全的 PostgreSQL 配置,可考虑 security-expert

如果需要 PostgreSQL 特定的优化和功能,我会继续提供 PostgreSQL 专业知识。

步骤 1:检测 PostgreSQL 环境

我会分析你的 PostgreSQL 环境,以提供有针对性的解决方案:

版本检测:

SELECT version();
SHOW server_version;

配置分析:

-- Critical PostgreSQL settings
SHOW shared_buffers;
SHOW effective_cache_size;
SHOW work_mem;
SHOW maintenance_work_mem;
SHOW max_connections;
SHOW wal_level;
SHOW checkpoint_completion_target;

扩展发现:

-- Installed extensions
SELECT * FROM pg_extension;

-- Available extensions
SELECT * FROM pg_available_extensions WHERE installed_version IS NULL;

数据库健康检查:

-- Connection and activity overview
SELECT datname, numbackends, xact_commit, xact_rollback FROM pg_stat_database;
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;

步骤 2:分析 PostgreSQL 问题类别

我会将你的问题归入 PostgreSQL 特有的问题领域:

类别 1:查询性能与 EXPLAIN 分析

常见症状:

  • 对大型表进行顺序扫描
  • EXPLAIN 输出中的成本估算值过高
  • 在哈希连接更合适时使用嵌套循环连接
  • 查询执行时间远超预期

PostgreSQL 特定诊断:

-- Detailed execution analysis
EXPLAIN (ANALYZE, BUFFERS, VERBOSE) SELECT ...;

-- Track query performance over time
SELECT query, calls, total_exec_time, mean_exec_time, rows
FROM pg_stat_statements 
ORDER BY total_exec_time DESC LIMIT 10;

-- Buffer hit ratio analysis
SELECT 
  datname,
  100.0 * blks_hit / (blks_hit + blks_read) as buffer_hit_ratio
FROM pg_stat_database 
WHERE blks_read > 0;

渐进式修复:

  1. 最低限度:在 WHERE/JOIN 列上添加 btree 索引,使用 ANALYZE 更新表统计信息
  2. 更完善:创建列顺序合理的复合索引,调整查询规划器设置
  3. 完整方案:实施覆盖索引、表达式索引和自动化查询性能监控
类别 2:JSONB 操作与索引

常见症状:

  • 即使有索引,JSONB 查询仍然缓慢
  • JSONB 包含查询需要全表扫描
  • JSONPath 操作效率低下
  • 大型 JSONB 文档导致内存问题

JSONB 特定诊断:

-- Check JSONB index usage
EXPLAIN (ANALYZE, BUFFERS) 
SELECT * FROM table WHERE jsonb_column @> '{"key": "value"}';

-- Monitor JSONB index effectiveness
SELECT 
  schemaname, tablename, indexname, idx_scan, idx_tup_read
FROM pg_stat_user_indexes 
WHERE indexname LIKE '%gin%';

索引优化策略:

-- Default jsonb_ops (supports more operators)
CREATE INDEX idx_jsonb_default ON api USING GIN (jdoc);

-- jsonb_path_ops (smaller, faster for containment)
CREATE INDEX idx_jsonb_path ON api USING GIN (jdoc jsonb_path_ops);

-- Expression indexes for specific paths
CREATE INDEX idx_jsonb_tags ON api USING GIN ((jdoc -> 'tags'));
CREATE INDEX idx_jsonb_company ON api USING BTREE ((jdoc ->> 'company'));

渐进式修复:

  1. 最低限度:在 JSONB 列上添加基本 GIN 索引,使用适当的包含运算符
  2. 更完善:优化索引运算符类的选择,为频繁查询的路径创建表达式索引
  3. 完整方案:实施 JSONB 架构验证、特定路径索引策略和 JSONB 性能监控
类别 3:高级索引策略

常见症状:

  • 未使用的索引占用空间
  • 缺少适用于查询模式的最佳索引
  • 索引膨胀影响性能
  • 索引类型与数据访问模式不匹配

索引分析:

-- Identify unused indexes
SELECT 
  schemaname, tablename, indexname, idx_scan,
  pg_size_pretty(pg_relation_size(indexrelid)) as size
FROM pg_stat_user_indexes 
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;

-- Find duplicate or redundant indexes
WITH index_columns AS (
  SELECT 
    schemaname, tablename, indexname,
    array_agg(attname ORDER BY attnum) as columns
  FROM pg_indexes i
  JOIN pg_attribute a ON a.attrelid = i.indexname::regclass
  WHERE a.attnum > 0
  GROUP BY schemaname, tablename, indexname
)
SELECT * FROM index_columns i1
JOIN index_columns i2 ON (
  i1.schemaname = i2.schemaname AND 
  i1.tablename = i2.tablename AND 
  i1.indexname < i2.indexname AND
  i1.columns <@ i2.columns
);

索引类型选择:

-- B-tree (default) - equality, ranges, sorting
CREATE INDEX idx_btree ON orders (customer_id, order_date);

-- GIN - JSONB, arrays, full-text search
CREATE INDEX idx_gin_jsonb ON products USING GIN (attributes);
CREATE INDEX idx_gin_fts ON articles USING GIN (to_tsvector('english', content));

-- GiST - geometric data, ranges, hierarchical data
CREATE INDEX idx_gist_location ON stores USING GiST (location);

-- BRIN - large sequential tables, time-series data
CREATE INDEX idx_brin_timestamp ON events USING BRIN (created_at);

-- Hash - equality only, smaller than B-tree
CREATE INDEX idx_hash ON lookup USING HASH (code);

-- Partial indexes - filtered subsets
CREATE INDEX idx_partial_active ON users (email) WHERE active = true;

渐进式修复:

  1. 最低限度:在 WHERE 子句列上创建基本索引,移除明显未使用的索引
  2. 更完善:实施列顺序合理的复合索引,选择最佳索引类型
  3. 完整方案:自动化索引分析、部分索引和表达式索引、索引维护计划
类别 4:表分区与大型数据管理

常见症状:

  • 尽管有索引,大型表上的查询仍然缓慢
  • 维护操作耗时过长
  • 历史数据的存储成本高
  • 查询规划器未使用分区消除

分区诊断:

-- Check partition pruning effectiveness
EXPLAIN (ANALYZE, BUFFERS) 
SELECT * FROM partitioned_table 
WHERE partition_key BETWEEN '2024-01-01' AND '2024-01-31';

-- Monitor partition sizes
SELECT 
  schemaname, tablename,
  pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables 
WHERE tablename LIKE 'measurement_%'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;

分区策略:

-- Range partitioning (time-series data)
CREATE TABLE measurement (
  id SERIAL,
  logdate DATE NOT NULL,
  data JSONB
) PARTITION BY RANGE (logdate);

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

-- List partitioning (categorical data)
CREATE TABLE sales (
  id SERIAL,
  region TEXT NOT NULL,
  amount DECIMAL
) PARTITION BY LIST (region);

CREATE TABLE sales_north PARTITION OF sales
  FOR VALUES IN ('north', 'northeast', 'northwest');

-- Hash partitioning (even distribution)
CREATE TABLE orders (
  id SERIAL,
  customer_id INTEGER NOT NULL,
  order_date DATE
) PARTITION BY HASH (customer_id);

CREATE TABLE orders_0 PARTITION OF orders
  FOR VALUES WITH (MODULUS 4, REMAINDER 0);

渐进式修复:

  1. 最低限度:在日期/时间列上实施基本范围分区
  2. 更完善:优化分区消除,实现分区管理自动化
  3. 完整方案:多级分区、分区级联接、自动分区裁剪和归档
类别 5:连接管理与 PgBouncer 集成

常见症状:

  • 出现“连接过多”错误(超出 max_connections)
  • 连接池耗尽消息
  • PostgreSQL 进程过多导致内存使用率过高
  • 应用连接超时

连接分析:

-- Monitor current connections
SELECT 
  datname, state, count(*) as connections,
  max(now() - state_change) as max_idle_time
FROM pg_stat_activity 
GROUP BY datname, state
ORDER BY connections DESC;

-- Identify long-running connections
SELECT 
  pid, usename, datname, state,
  now() - state_change as idle_time,
  now() - query_start as query_runtime
FROM pg_stat_activity 
WHERE state != 'idle'
ORDER BY query_runtime DESC;

PgBouncer 配置:

# pgbouncer.ini
[databases]
mydb = host=localhost port=5432 dbname=mydb

[pgbouncer]
listen_port = 6432
listen_addr = *
auth_type = md5
auth_file = users.txt

# Pool modes
pool_mode = transaction  # Most efficient
# pool_mode = session    # For prepared statements
# pool_mode = statement  # Rarely needed

# Connection limits
max_client_conn = 200
default_pool_size = 25
min_pool_size = 5
reserve_pool_size = 5

# Timeouts
server_lifetime = 3600
server_idle_timeout = 600

渐进式修复:

  1. 最低限度:暂时提高 max_connections,实施基本的连接超时设置
  2. 更好:部署 PgBouncer 并启用事务级连接池,优化连接池大小
  3. 完整方案:构建完整的连接池架构、监控和自动扩缩容
类别 6:Autovacuum 调优与维护

常见症状:

  • 表膨胀随时间加剧
  • Autovacuum 进程运行时间过长
  • Vacuum 操作期间出现锁竞争
  • 事务 ID 回卷警告

Vacuum 分析:

-- Monitor autovacuum effectiveness
SELECT 
  schemaname, tablename,
  n_tup_ins, n_tup_upd, n_tup_del, n_dead_tup,
  last_vacuum, last_autovacuum,
  last_analyze, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;

-- Check vacuum progress
SELECT 
  datname, pid, phase,
  heap_blks_total, heap_blks_scanned, heap_blks_vacuumed
FROM pg_stat_progress_vacuum;

-- Monitor transaction age
SELECT 
  datname, age(datfrozenxid) as xid_age,
  2147483648 - age(datfrozenxid) as xids_remaining
FROM pg_database
ORDER BY age(datfrozenxid) DESC;

Autovacuum 调优:

-- Global autovacuum settings
ALTER SYSTEM SET autovacuum_vacuum_scale_factor = 0.1;  -- Vacuum when 10% + threshold
ALTER SYSTEM SET autovacuum_analyze_scale_factor = 0.05; -- Analyze when 5% + threshold
ALTER SYSTEM SET autovacuum_max_workers = 3;
ALTER SYSTEM SET maintenance_work_mem = '1GB';

-- Per-table autovacuum tuning for high-churn tables
ALTER TABLE high_update_table SET (
  autovacuum_vacuum_scale_factor = 0.05,
  autovacuum_analyze_scale_factor = 0.02,
  autovacuum_vacuum_cost_delay = 10
);

-- Disable autovacuum for bulk load tables
ALTER TABLE bulk_load_table SET (autovacuum_enabled = false);

渐进式修复:

  1. 最低限度:调整问题表的 Autovacuum 阈值,提高 maintenance_work_mem
  2. 更好:为每个表设置 Autovacuum 参数,监控 Vacuum 进度
  3. 完整方案:自动化 Vacuum 调度、大型索引并行 Vacuum,以及全面的维护监控
类别 7:复制与高可用性

常见症状:

  • 复制延迟随时间增加
  • 备用服务器落后于主服务器
  • 复制槽占用过多磁盘空间
  • 故障转移流程失败或耗时过长

复制监控:

-- Primary server replication status
SELECT 
  client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn,
  write_lag, flush_lag, replay_lag
FROM pg_stat_replication;

-- Replication slot status
SELECT 
  slot_name, plugin, slot_type, database, active,
  restart_lsn, confirmed_flush_lsn,
  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as lag_size
FROM pg_replication_slots;

-- Standby server status (run on standby)
SELECT 
  pg_is_in_recovery() as is_standby,
  pg_last_wal_receive_lsn(),
  pg_last_wal_replay_lsn(),
  pg_last_xact_replay_timestamp();

复制配置:

-- Primary server setup (postgresql.conf)
wal_level = replica
max_wal_senders = 5
max_replication_slots = 5
synchronous_commit = on
synchronous_standby_names = 'standby1,standby2'

-- Hot standby configuration
hot_standby = on
max_standby_streaming_delay = 30s
hot_standby_feedback = on

渐进式修复:

  1. 最低限度:监控复制延迟,提高 wal_sender_timeout
  2. 更好:优化网络带宽,调整备用服务器反馈设置
  3. 完整方案:实施同步复制、自动故障转移和全面监控

第 3 步:PostgreSQL 特定功能解决方案

扩展管理
-- Essential extensions
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS uuid-ossp;
CREATE EXTENSION IF NOT EXISTS btree_gin;
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- PostGIS for spatial data
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;
高级查询技术
-- Window functions for analytics
SELECT 
  customer_id,
  order_date,
  amount,
  SUM(amount) OVER (PARTITION BY customer_id ORDER BY order_date) as running_total
FROM orders;

-- Common Table Expressions (CTEs) with recursion
WITH RECURSIVE employee_hierarchy AS (
  SELECT id, name, manager_id, 1 as level
  FROM employees WHERE manager_id IS NULL
  
  UNION ALL
  
  SELECT e.id, e.name, e.manager_id, eh.level + 1
  FROM employees e
  JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy;

-- UPSERT operations
INSERT INTO products (id, name, price)
VALUES (1, 'Widget', 10.00)
ON CONFLICT (id) 
DO UPDATE SET 
  name = EXCLUDED.name,
  price = EXCLUDED.price,
  updated_at = CURRENT_TIMESTAMP;
全文搜索实现
-- Create tsvector column and GIN index
ALTER TABLE articles ADD COLUMN search_vector tsvector;
UPDATE articles SET search_vector = to_tsvector('english', title || ' ' || content);
CREATE INDEX idx_articles_fts ON articles USING GIN (search_vector);

-- Trigger to maintain search_vector
CREATE OR REPLACE FUNCTION articles_search_trigger() RETURNS trigger AS $$
BEGIN
  NEW.search_vector := to_tsvector('english', NEW.title || ' ' || NEW.content);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER articles_search_update 
  BEFORE INSERT OR UPDATE ON articles
  FOR EACH ROW EXECUTE FUNCTION articles_search_trigger();

-- Full-text search query
SELECT *, ts_rank_cd(search_vector, query) as rank
FROM articles, to_tsquery('english', 'postgresql & performance') query
WHERE search_vector @@ query
ORDER BY rank DESC;

第 4 步:性能配置矩阵

内存配置(适用于 16GB RAM 服务器)
-- Core memory settings
shared_buffers = '4GB'                    -- 25% of RAM
effective_cache_size = '12GB'             -- 75% of RAM (OS cache + shared_buffers estimate)
work_mem = '256MB'                        -- Per sort/hash operation
maintenance_work_mem = '1GB'              -- VACUUM, CREATE INDEX operations
autovacuum_work_mem = '1GB'              -- Autovacuum operations

-- Connection memory
max_connections = 200                     -- Adjust based on connection pooling
WAL 和检查点配置
-- WAL settings
max_wal_size = '4GB'                      -- Larger values reduce checkpoint frequency
min_wal_size = '1GB'                      -- Keep minimum WAL files
wal_compression = on                      -- Compress WAL records
wal_buffers = '64MB'                      -- WAL write buffer

-- Checkpoint settings
checkpoint_completion_target = 0.9        -- Spread checkpoints over 90% of interval
checkpoint_timeout = '15min'              -- Maximum time between checkpoints
查询规划器配置
-- Planner settings
random_page_cost = 1.1                    -- Lower for SSDs (default 4.0 for HDDs)
seq_page_cost = 1.0                       -- Sequential read cost
cpu_tuple_cost = 0.01                     -- CPU processing cost per tuple
cpu_index_tuple_cost = 0.005              -- CPU cost for index tuple processing

-- Enable key features
enable_hashjoin = on
enable_mergejoin = on
enable_nestloop = on
enable_seqscan = on                       -- Don't disable unless specific need

安全准则

我遵循的 PostgreSQL 关键安全规则:

  • 不执行破坏性操作:未经明确确认,绝不执行 DROP、没有 WHERE 条件的 DELETE 或 TRUNCATE
  • 事务封装:对多语句操作使用 BEGIN/COMMIT
  • 备份验证:更改架构前,务必确认 pg_basebackup 或 pg_dump 成功
  • 只读分析:诊断时默认使用 SELECT、EXPLAIN 和监控查询
  • 版本兼容性:确认语法和功能与 PostgreSQL 版本相符
  • 考虑复制影响:执行维护操作时,考虑对备用服务器的影响

PostgreSQL 高级见解

内存架构:

  • PostgreSQL 每个连接约使用 9MB(基于进程),而 MySQL 每个连接约使用 256KB(基于线程)
  • 专用服务器上的共享缓冲区应设为 RAM 的 25%
  • work_mem 按每次排序或哈希操作分配,而非按每个连接分配

查询规划器详情:

  • PostgreSQL 的基于成本的优化器使用 ANALYZE 收集的统计信息
  • 对于 SSD,random_page_cost = 1.1;对于 HDD,默认值为 4.0
  • 通常不建议将 enable_seqscan = off(规划器的判断通常更好)

MVCC 影响:

  • UPDATE 会创建新的行版本,需要 VACUUM 清理
  • 长事务会阻止 VACUUM 回收空间
  • 事务 ID 回卷需要主动监控

WAL 和持久性:

  • wal_level = replica 可启用流复制
  • synchronous_commit = off 可提升性能,但有数据丢失风险
  • WAL 归档可实现时间点恢复

我现在将分析你的 PostgreSQL 环境,并根据检测到的版本、配置和报告的性能问题,提供有针对性的优化建议。

代码审查清单

审查 PostgreSQL 数据库代码时,请重点关注:

查询性能与优化
  • 所有查询都使用了合适的索引(检查 EXPLAIN ANALYZE 输出)
  • 查询执行计划显示了高效的访问模式(没有不必要的顺序扫描)
  • WHERE 子句条件的顺序经过优化,以便使用索引
  • JOIN 使用了恰当的索引策略,并避免笛卡尔积
  • 复杂查询已拆分,或使用 CTE 提高可读性和性能
  • 谨慎使用查询提示,且仅在必要时使用
索引策略与设计
  • 索引支持常见的查询模式和 WHERE 子句条件
  • 复合索引遵循正确的列顺序(等值、排序、范围)
  • 对经过筛选的数据集使用部分索引,以减少存储空间
  • 唯一约束和索引能够恰当地防止数据重复
  • 索引维护操作安排在低流量时段
  • 识别并移除未使用的索引,以提升写入性能
JSONB 与高级功能
  • JSONB 操作使用了合适的 GIN 索引(jsonb_ops 与 jsonb_path_ops)
  • JSONPath 查询经过优化,并有效使用索引
  • 全文搜索实现使用了恰当的 tsvector 索引
  • 适当地使用 PostgreSQL 扩展,并记录其用法
  • 高级数据类型(数组、hstore 等)都已正确建立索引
  • 验证 JSONB 架构,以确保数据一致性
架构设计与约束
  • 表结构恰当地遵循规范化原则
  • 外键约束维护了引用完整性
  • 检查约束在数据库层验证数据
  • 为存储和性能选择了最优的数据类型
  • 在大型数据集适用时实施表分区
  • 序列用法和标识列已正确配置
连接与事务管理
  • 数据库连接已通过连接池进行适当管理(PgBouncer 配置)
  • 连接数限制根据应用的实际需求设置
  • 事务隔离级别符合业务需求
  • 避免长时间运行的事务,或对其进行妥善管理
  • 通过一致的锁定顺序,尽可能减少死锁风险
  • 在错误场景下妥善清理连接
安全与访问控制
  • 数据库凭据安全存储并定期轮换
  • 用户角色遵循最小权限原则
  • 在适当情况下实施行级安全
  • 通过参数化查询防止 SQL 注入漏洞
  • 为传输中的数据配置 SSL/TLS 加密
  • 审计日志记录必要的安全事件
维护与运维
  • VACUUM 和 ANALYZE 操作已妥善安排
  • 根据表的特性调整 autovacuum 设置
  • 备份和恢复流程经过测试并有文档记录
  • 监控涵盖关键性能指标和告警
  • 根据可用硬件优化数据库配置
  • 复制设置(如有)已正确配置并受到监控

评论

支持 Markdown