postgresql

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PostgreSQL Core Knowledge

PostgreSQL 核心知识

Deep Knowledge: Use
mcp__documentation__fetch_docs
with technology:
postgresql
for comprehensive documentation.
深度知识库:如需获取完整文档,请调用
mcp__documentation__fetch_docs
工具并指定技术栈为
postgresql

Table Definition

表定义

sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_active BOOLEAN DEFAULT TRUE
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created ON users(created_at DESC);
sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_active BOOLEAN DEFAULT TRUE
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created ON users(created_at DESC);

Common Queries

常用查询

sql
-- Select with pagination
SELECT * FROM users
WHERE is_active = TRUE
ORDER BY created_at DESC
LIMIT 20 OFFSET 0;

-- Join
SELECT u.*, p.title
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
WHERE u.id = $1;

-- Aggregate
SELECT
    DATE_TRUNC('day', created_at) as day,
    COUNT(*) as count
FROM users
GROUP BY DATE_TRUNC('day', created_at)
ORDER BY day DESC;

-- Upsert
INSERT INTO users (email, name)
VALUES ($1, $2)
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name;
sql
-- 分页查询
SELECT * FROM users
WHERE is_active = TRUE
ORDER BY created_at DESC
LIMIT 20 OFFSET 0;

-- 关联查询
SELECT u.*, p.title
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
WHERE u.id = $1;

-- 聚合查询
SELECT
    DATE_TRUNC('day', created_at) as day,
    COUNT(*) as count
FROM users
GROUP BY DATE_TRUNC('day', created_at)
ORDER BY day DESC;

-- 写入更新(Upsert)
INSERT INTO users (email, name)
VALUES ($1, $2)
ON CONFLICT (email)
DO UPDATE SET name = EXCLUDED.name;

Data Types

数据类型

TypeUse For
SERIAL
Auto-increment IDs
UUID
Unique identifiers
VARCHAR(n)
Variable strings
TEXT
Long text
JSONB
JSON data (indexed)
TIMESTAMP
Date and time
BOOLEAN
True/false
类型用途
SERIAL
自增ID
UUID
唯一标识符
VARCHAR(n)
可变长度字符串
TEXT
长文本
JSONB
可索引的JSON数据
TIMESTAMP
日期时间
BOOLEAN
布尔值

Performance

性能优化

  • Use
    EXPLAIN ANALYZE
    to check queries
  • Add indexes for WHERE/JOIN columns
  • Use
    JSONB
    over
    JSON
    for queries
  • Partial indexes for filtered queries
  • 使用
    EXPLAIN ANALYZE
    分析查询执行计划
  • 为 WHERE/JOIN 涉及的列添加索引
  • 查询场景下优先使用
    JSONB
    而非
    JSON
  • 针对过滤查询使用部分索引

When NOT to Use This Skill

本技能不适用场景

  • MySQL-specific syntax - Use
    mysql
    skill for MySQL databases (AUTO_INCREMENT, GROUP_CONCAT)
  • NoSQL operations - Use
    mongodb
    or
    redis
    skills for document/key-value stores
  • Oracle PL/SQL - Use
    plsql
    skill for Oracle-specific procedural code
  • SQL Server T-SQL - Use
    tsql
    skill for SQL Server-specific features
  • ORM abstractions - Use framework-specific skills (Prisma, TypeORM, Spring Data JPA)
  • MySQL 专属语法:MySQL 数据库相关问题(如 AUTO_INCREMENT、GROUP_CONCAT)请使用
    mysql
    技能
  • NoSQL 操作:文档/键值存储相关问题请使用
    mongodb
    redis
    技能
  • Oracle PL/SQL:Oracle 专属存储过程代码相关问题请使用
    plsql
    技能
  • SQL Server T-SQL:SQL Server 专属特性相关问题请使用
    tsql
    技能
  • ORM 抽象层:ORM 框架相关问题请使用对应框架技能(如 Prisma、TypeORM、Spring Data JPA)

Anti-Patterns

反模式

Anti-PatternIssueSolution
SELECT *
in production
Transfers unnecessary data, breaks when schema changesSpecify needed columns explicitly
Missing
WHERE
on UPDATE/DELETE
Modifies all rows unintentionallyAlways include WHERE clause, use transactions
Missing indexes on JOIN/WHERE columnsFull table scans, slow queriesAdd indexes on frequently queried columns
Using functions on indexed columnsPrevents index usage:
WHERE UPPER(email) = 'X'
Use functional indexes or change query
LIKE '%pattern'
Cannot use index, full scanUse
LIKE 'pattern%'
or full-text search
Missing
LIMIT
on large tables
Can crash application, memory issuesAlways paginate results
Storing comma-separated valuesCannot query efficiently, violates normalizationUse array type or junction table
Missing foreign keysData integrity issues, orphaned recordsDefine proper FK constraints
N+1 query problemOne query per row in loopUse JOINs or batch queries
Long-running transactionsLocks resources, blocks other queriesKeep transactions short, use appropriate isolation
反模式问题解决方案
生产环境使用
SELECT *
传输不必要数据, schema 变更时容易报错显式指定需要查询的列
UPDATE/DELETE 语句缺少
WHERE
条件
意外修改全表数据始终携带 WHERE 条件,使用事务
JOIN/WHERE 涉及的列缺少索引触发全表扫描,查询缓慢为高频查询列添加索引
对索引列使用函数导致索引失效,比如
WHERE UPPER(email) = 'X'
使用函数索引或改写查询语句
使用
LIKE '%pattern'
前缀模糊查询
无法使用索引,触发全表扫描使用
LIKE 'pattern%'
后缀查询或全文搜索
大表查询缺少
LIMIT
限制
可能导致应用崩溃,引发内存问题始终对结果分页
存储逗号分隔的数值查询效率低下,违反范式要求使用数组类型或关联表
缺少外键约束存在数据完整性问题,产生孤立数据定义正确的外键约束
N+1 查询问题循环中逐行发起查询使用 JOIN 或批量查询
长事务锁定资源,阻塞其他查询缩短事务执行时长,使用合适的隔离级别

Quick Troubleshooting

快速故障排查

ProblemDiagnosticFix
Slow queries
EXPLAIN ANALYZE query
Add indexes, rewrite query, update statistics
High CPU usage
pg_stat_statements
to find slow queries
Optimize top queries, add connection pooling
Connection limit reached
SELECT count(*) FROM pg_stat_activity
Increase max_connections, use PgBouncer
Lock contention
SELECT * FROM pg_locks WHERE NOT granted
Reduce transaction time, use lower isolation
Disk space full
SELECT pg_size_pretty(pg_database_size('mydb'))
VACUUM, archive old data, increase storage
Replication lagCheck
pg_stat_replication
Increase resources, tune checkpoint settings
Cache hit ratio < 95%
SELECT sum(blks_hit)/sum(blks_hit+blks_read) FROM pg_stat_database
Increase shared_buffers
Dead tuples accumulating
SELECT n_dead_tup FROM pg_stat_user_tables
Run VACUUM, tune autovacuum
问题诊断方法修复方案
查询缓慢执行
EXPLAIN ANALYZE 待分析查询语句
添加索引、改写查询、更新统计信息
CPU 使用率过高使用
pg_stat_statements
定位慢查询
优化Top慢查询、添加连接池
连接数达到上限执行
SELECT count(*) FROM pg_stat_activity
调大 max_connections 参数、使用 PgBouncer
锁竞争执行
SELECT * FROM pg_locks WHERE NOT granted
缩短事务执行时间、降低隔离级别
磁盘空间不足执行
SELECT pg_size_pretty(pg_database_size('mydb'))
执行 VACUUM、归档旧数据、扩容存储
复制延迟查看
pg_stat_replication
提升资源配置、调优检查点设置
缓存命中率低于95%执行
SELECT sum(blks_hit)/sum(blks_hit+blks_read) FROM pg_stat_database
调大 shared_buffers 参数
死元组堆积执行
SELECT n_dead_tup FROM pg_stat_user_tables
执行 VACUUM、调优自动清理配置

Production Readiness

生产环境就绪指南

Security Configuration

安全配置

sql
-- Create application user with limited privileges
CREATE USER app_user WITH PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE mydb TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;

-- Row Level Security (RLS)
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY users_tenant_isolation ON users
    USING (tenant_id = current_setting('app.tenant_id')::uuid);

-- Force SSL connections
-- In postgresql.conf:
-- ssl = on
-- ssl_cert_file = '/path/to/server.crt'
-- ssl_key_file = '/path/to/server.key'
sql
-- Connection with SSL
psql "postgresql://user:pass@host:5432/db?sslmode=require"
sql
-- 创建最小权限的应用用户
CREATE USER app_user WITH PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE mydb TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;

-- 行级安全(RLS)
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY users_tenant_isolation ON users
    USING (tenant_id = current_setting('app.tenant_id')::uuid);

-- 强制 SSL 连接
-- 在 postgresql.conf 中配置:
-- ssl = on
-- ssl_cert_file = '/path/to/server.crt'
-- ssl_key_file = '/path/to/server.key'
sql
-- SSL 方式连接
psql "postgresql://user:pass@host:5432/db?sslmode=require"

Connection Pooling (PgBouncer)

连接池(PgBouncer)

ini
undefined
ini
undefined

pgbouncer.ini

pgbouncer.ini 配置

[databases] mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer] listen_addr = 0.0.0.0 listen_port = 6432 auth_type = md5 auth_file = /etc/pgbouncer/userlist.txt pool_mode = transaction max_client_conn = 1000 default_pool_size = 20 min_pool_size = 5 reserve_pool_size = 5
undefined
[databases] mydb = host=127.0.0.1 port=5432 dbname=mydb
[pgbouncer] listen_addr = 0.0.0.0 listen_port = 6432 auth_type = md5 auth_file = /etc/pgbouncer/userlist.txt pool_mode = transaction max_client_conn = 1000 default_pool_size = 20 min_pool_size = 5 reserve_pool_size = 5
undefined

Backup & Recovery

备份与恢复

bash
undefined
bash
undefined

Continuous archiving (WAL)

持续归档(WAL)

postgresql.conf:

postgresql.conf 配置:

archive_mode = on archive_command = 'cp %p /backup/wal/%f' wal_level = replica
archive_mode = on archive_command = 'cp %p /backup/wal/%f' wal_level = replica

Full backup with pg_basebackup

使用 pg_basebackup 全量备份

pg_basebackup -D /backup/base -Ft -Xs -P -U replication
pg_basebackup -D /backup/base -Ft -Xs -P -U replication

Point-in-time recovery (recovery.signal)

时间点恢复(recovery.signal 配置)

restore_command = 'cp /backup/wal/%f %p' recovery_target_time = '2024-01-15 10:00:00'
undefined
restore_command = 'cp /backup/wal/%f %p' recovery_target_time = '2024-01-15 10:00:00'
undefined

Performance Tuning

性能调优

sql
-- postgresql.conf recommendations (for 16GB RAM server)
shared_buffers = 4GB                # 25% of RAM
effective_cache_size = 12GB         # 75% of RAM
maintenance_work_mem = 1GB
work_mem = 64MB
wal_buffers = 64MB
max_connections = 200
checkpoint_completion_target = 0.9
random_page_cost = 1.1              # SSD

-- Query optimization
SET log_min_duration_statement = 1000;  -- Log queries > 1s
ANALYZE;  -- Update statistics
sql
-- postgresql.conf 配置建议(针对16GB内存服务器)
shared_buffers = 4GB                # 总内存的25%
effective_cache_size = 12GB         # 总内存的75%
maintenance_work_mem = 1GB
work_mem = 64MB
wal_buffers = 64MB
max_connections = 200
checkpoint_completion_target = 0.9
random_page_cost = 1.1              # SSD场景配置

-- 查询优化
SET log_min_duration_statement = 1000;  -- 记录执行耗时超过1秒的查询
ANALYZE;  -- 更新统计信息

Monitoring Metrics

监控指标

MetricAlert Threshold
Connection count> 80% max_connections
Cache hit ratio< 95%
Replication lag> 1MB or > 10s
Dead tuples ratio> 10%
Long-running transactions> 5 minutes
Lock wait events> 10/min
指标告警阈值
连接数超过 max_connections 的80%
缓存命中率低于95%
复制延迟超过1MB 或 10秒
死元组占比超过10%
长事务执行时长超过5分钟
锁等待事件每分钟超过10次

Monitoring Queries

监控查询

sql
-- Active connections
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';

-- Cache hit ratio
SELECT
    round(100 * sum(blks_hit) / nullif(sum(blks_hit) + sum(blks_read), 0), 2) as cache_hit_ratio
FROM pg_stat_database;

-- Table bloat (dead tuples)
SELECT schemaname, relname, n_dead_tup, n_live_tup,
       round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) as dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;

-- Long-running queries
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active' AND now() - pg_stat_activity.query_start > interval '5 minutes';

-- Replication lag
SELECT client_addr, state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS send_lag,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag
FROM pg_stat_replication;
sql
-- 活跃连接数
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';

-- 缓存命中率
SELECT
    round(100 * sum(blks_hit) / nullif(sum(blks_hit) + sum(blks_read), 0), 2) as cache_hit_ratio
FROM pg_stat_database;

-- 表膨胀(死元组)
SELECT schemaname, relname, n_dead_tup, n_live_tup,
       round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) as dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;

-- 长运行查询
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active' AND now() - pg_stat_activity.query_start > interval '5 minutes';

-- 复制延迟
SELECT client_addr, state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) AS send_lag,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag
FROM pg_stat_replication;

High Availability

高可用

yaml
undefined
yaml
undefined

Patroni configuration for HA

Patroni 高可用配置示例

scope: postgres-cluster name: node1
restapi: listen: 0.0.0.0:8008
etcd: hosts: etcd1:2379,etcd2:2379,etcd3:2379
postgresql: listen: 0.0.0.0:5432 data_dir: /data/postgres parameters: max_connections: 200 shared_buffers: 4GB
undefined
scope: postgres-cluster name: node1
restapi: listen: 0.0.0.0:8008
etcd: hosts: etcd1:2379,etcd2:2379,etcd3:2379
postgresql: listen: 0.0.0.0:5432 data_dir: /data/postgres parameters: max_connections: 200 shared_buffers: 4GB
undefined

Checklist

检查清单

  • SSL/TLS encryption enabled
  • Least-privilege user accounts
  • Connection pooling (PgBouncer)
  • WAL archiving configured
  • Regular pg_dump backups
  • Point-in-time recovery tested
  • Monitoring queries in place
  • Slow query logging enabled
  • VACUUM/ANALYZE scheduled
  • Replication configured (if HA)
  • Connection limits set
  • Row Level Security (if multi-tenant)
  • 已开启 SSL/TLS 加密
  • 已配置最小权限用户账号
  • 已配置连接池(PgBouncer)
  • 已配置 WAL 归档
  • 已设置定期 pg_dump 备份
  • 已验证时间点恢复可用
  • 已配置监控查询规则
  • 已开启慢查询日志
  • 已设置定时 VACUUM/ANALYZE 任务
  • 已配置数据复制(如需高可用)
  • 已设置连接数上限
  • 已开启行级安全(多租户场景)

Reference Documentation

参考文档

  • Indexes
  • JSON Queries
  • 索引
  • JSON 查询