postgresql-optimization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePostgreSQL Development Assistant
PostgreSQL开发助手
Expert PostgreSQL guidance for ${selection} (or entire project if no selection). Focus on PostgreSQL-specific features, optimization patterns, and advanced capabilities.
针对${selection}(若未选中则针对整个项目)的专业PostgreSQL指导。聚焦PostgreSQL专属功能、优化模式及高级能力。
� PostgreSQL-Specific Features
🎯 PostgreSQL专属功能
JSONB Operations
JSONB操作
sql
-- Advanced JSONB queries
CREATE TABLE events (
id SERIAL PRIMARY KEY,
data JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- GIN index for JSONB performance
CREATE INDEX idx_events_data_gin ON events USING gin(data);
-- JSONB containment and path queries
SELECT * FROM events
WHERE data @> '{"type": "login"}'
AND data #>> '{user,role}' = 'admin';
-- JSONB aggregation
SELECT jsonb_agg(data) FROM events WHERE data ? 'user_id';sql
-- Advanced JSONB queries
CREATE TABLE events (
id SERIAL PRIMARY KEY,
data JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- GIN index for JSONB performance
CREATE INDEX idx_events_data_gin ON events USING gin(data);
-- JSONB containment and path queries
SELECT * FROM events
WHERE data @> '{"type": "login"}'
AND data #>> '{user,role}' = 'admin';
-- JSONB aggregation
SELECT jsonb_agg(data) FROM events WHERE data ? 'user_id';Array Operations
数组操作
sql
-- PostgreSQL arrays
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
tags TEXT[],
categories INTEGER[]
);
-- Array queries and operations
SELECT * FROM posts WHERE 'postgresql' = ANY(tags);
SELECT * FROM posts WHERE tags && ARRAY['database', 'sql'];
SELECT * FROM posts WHERE array_length(tags, 1) > 3;
-- Array aggregation
SELECT array_agg(DISTINCT category) FROM posts, unnest(categories) as category;sql
-- PostgreSQL arrays
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
tags TEXT[],
categories INTEGER[]
);
-- Array queries and operations
SELECT * FROM posts WHERE 'postgresql' = ANY(tags);
SELECT * FROM posts WHERE tags && ARRAY['database', 'sql'];
SELECT * FROM posts WHERE array_length(tags, 1) > 3;
-- Array aggregation
SELECT array_agg(DISTINCT category) FROM posts, unnest(categories) as category;Window Functions & Analytics
窗口函数与分析
sql
-- Advanced window functions
SELECT
product_id,
sale_date,
amount,
-- Running totals
SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) as running_total,
-- Moving averages
AVG(amount) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) as moving_avg,
-- Rankings
DENSE_RANK() OVER (PARTITION BY EXTRACT(month FROM sale_date) ORDER BY amount DESC) as monthly_rank,
-- Lag/Lead for comparisons
LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date) as prev_amount
FROM sales;sql
-- Advanced window functions
SELECT
product_id,
sale_date,
amount,
-- Running totals
SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) as running_total,
-- Moving averages
AVG(amount) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) as moving_avg,
-- Rankings
DENSE_RANK() OVER (PARTITION BY EXTRACT(month FROM sale_date) ORDER BY amount DESC) as monthly_rank,
-- Lag/Lead for comparisons
LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date) as prev_amount
FROM sales;Full-Text Search
全文搜索
sql
-- PostgreSQL full-text search
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
search_vector tsvector
);
-- Update search vector
UPDATE documents
SET search_vector = to_tsvector('english', title || ' ' || content);
-- GIN index for search performance
CREATE INDEX idx_documents_search ON documents USING gin(search_vector);
-- Search queries
SELECT * FROM documents
WHERE search_vector @@ plainto_tsquery('english', 'postgresql database');
-- Ranking results
SELECT *, ts_rank(search_vector, plainto_tsquery('postgresql')) as rank
FROM documents
WHERE search_vector @@ plainto_tsquery('postgresql')
ORDER BY rank DESC;sql
-- PostgreSQL full-text search
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
search_vector tsvector
);
-- Update search vector
UPDATE documents
SET search_vector = to_tsvector('english', title || ' ' || content);
-- GIN index for search performance
CREATE INDEX idx_documents_search ON documents USING gin(search_vector);
-- Search queries
SELECT * FROM documents
WHERE search_vector @@ plainto_tsquery('english', 'postgresql database');
-- Ranking results
SELECT *, ts_rank(search_vector, plainto_tsquery('postgresql')) as rank
FROM documents
WHERE search_vector @@ plainto_tsquery('postgresql')
ORDER BY rank DESC;� PostgreSQL Performance Tuning
🚀 PostgreSQL性能调优
Query Optimization
查询优化
sql
-- EXPLAIN ANALYZE for performance analysis
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01'::date
GROUP BY u.id, u.name;
-- Identify slow queries from pg_stat_statements
SELECT query, calls, total_time, mean_time, rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;sql
-- EXPLAIN ANALYZE for performance analysis
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01'::date
GROUP BY u.id, u.name;
-- Identify slow queries from pg_stat_statements
SELECT query, calls, total_time, mean_time, rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;Index Strategies
索引策略
sql
-- Composite indexes for multi-column queries
CREATE INDEX idx_orders_user_date ON orders(user_id, order_date);
-- Partial indexes for filtered queries
CREATE INDEX idx_active_users ON users(created_at) WHERE status = 'active';
-- Expression indexes for computed values
CREATE INDEX idx_users_lower_email ON users(lower(email));
-- Covering indexes to avoid table lookups
CREATE INDEX idx_orders_covering ON orders(user_id, status) INCLUDE (total, created_at);sql
-- Composite indexes for multi-column queries
CREATE INDEX idx_orders_user_date ON orders(user_id, order_date);
-- Partial indexes for filtered queries
CREATE INDEX idx_active_users ON users(created_at) WHERE status = 'active';
-- Expression indexes for computed values
CREATE INDEX idx_users_lower_email ON users(lower(email));
-- Covering indexes to avoid table lookups
CREATE INDEX idx_orders_covering ON orders(user_id, status) INCLUDE (total, created_at);Connection & Memory Management
连接与内存管理
sql
-- Check connection usage
SELECT count(*) as connections, state
FROM pg_stat_activity
GROUP BY state;
-- Monitor memory usage
SELECT name, setting, unit
FROM pg_settings
WHERE name IN ('shared_buffers', 'work_mem', 'maintenance_work_mem');sql
-- Check connection usage
SELECT count(*) as connections, state
FROM pg_stat_activity
GROUP BY state;
-- Monitor memory usage
SELECT name, setting, unit
FROM pg_settings
WHERE name IN ('shared_buffers', 'work_mem', 'maintenance_work_mem');�️ PostgreSQL Advanced Data Types
🛠️ PostgreSQL高级数据类型
Custom Types & Domains
自定义类型与域
sql
-- Create custom types
CREATE TYPE address_type AS (
street TEXT,
city TEXT,
postal_code TEXT,
country TEXT
);
CREATE TYPE order_status AS ENUM ('pending', 'processing', 'shipped', 'delivered', 'cancelled');
-- Use domains for data validation
CREATE DOMAIN email_address AS TEXT
CHECK (VALUE ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
-- Table using custom types
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
email email_address NOT NULL,
address address_type,
status order_status DEFAULT 'pending'
);sql
-- Create custom types
CREATE TYPE address_type AS (
street TEXT,
city TEXT,
postal_code TEXT,
country TEXT
);
CREATE TYPE order_status AS ENUM ('pending', 'processing', 'shipped', 'delivered', 'cancelled');
-- Use domains for data validation
CREATE DOMAIN email_address AS TEXT
CHECK (VALUE ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
-- Table using custom types
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
email email_address NOT NULL,
address address_type,
status order_status DEFAULT 'pending'
);Range Types
范围类型
sql
-- PostgreSQL range types
CREATE TABLE reservations (
id SERIAL PRIMARY KEY,
room_id INTEGER,
reservation_period tstzrange,
price_range numrange
);
-- Range queries
SELECT * FROM reservations
WHERE reservation_period && tstzrange('2024-07-20', '2024-07-25');
-- Exclude overlapping ranges
ALTER TABLE reservations
ADD CONSTRAINT no_overlap
EXCLUDE USING gist (room_id WITH =, reservation_period WITH &&);sql
-- PostgreSQL range types
CREATE TABLE reservations (
id SERIAL PRIMARY KEY,
room_id INTEGER,
reservation_period tstzrange,
price_range numrange
);
-- Range queries
SELECT * FROM reservations
WHERE reservation_period && tstzrange('2024-07-20', '2024-07-25');
-- Exclude overlapping ranges
ALTER TABLE reservations
ADD CONSTRAINT no_overlap
EXCLUDE USING gist (room_id WITH =, reservation_period WITH &&);Geometric Types
几何类型
sql
-- PostgreSQL geometric types
CREATE TABLE locations (
id SERIAL PRIMARY KEY,
name TEXT,
coordinates POINT,
coverage CIRCLE,
service_area POLYGON
);
-- Geometric queries
SELECT name FROM locations
WHERE coordinates <-> point(40.7128, -74.0060) < 10; -- Within 10 units
-- GiST index for geometric data
CREATE INDEX idx_locations_coords ON locations USING gist(coordinates);sql
-- PostgreSQL geometric types
CREATE TABLE locations (
id SERIAL PRIMARY KEY,
name TEXT,
coordinates POINT,
coverage CIRCLE,
service_area POLYGON
);
-- Geometric queries
SELECT name FROM locations
WHERE coordinates <-> point(40.7128, -74.0060) < 10; -- Within 10 units
-- GiST index for geometric data
CREATE INDEX idx_locations_coords ON locations USING gist(coordinates);📊 PostgreSQL Extensions & Tools
📊 PostgreSQL扩展与工具
Useful Extensions
实用扩展
sql
-- Enable commonly used extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- Cryptographic functions
CREATE EXTENSION IF NOT EXISTS "unaccent"; -- Remove accents from text
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Trigram matching
CREATE EXTENSION IF NOT EXISTS "btree_gin"; -- GIN indexes for btree types
-- Using extensions
SELECT uuid_generate_v4(); -- Generate UUIDs
SELECT crypt('password', gen_salt('bf')); -- Hash passwords
SELECT similarity('postgresql', 'postgersql'); -- Fuzzy matchingsql
-- Enable commonly used extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- Cryptographic functions
CREATE EXTENSION IF NOT EXISTS "unaccent"; -- Remove accents from text
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Trigram matching
CREATE EXTENSION IF NOT EXISTS "btree_gin"; -- GIN indexes for btree types
-- Using extensions
SELECT uuid_generate_v4(); -- Generate UUIDs
SELECT crypt('password', gen_salt('bf')); -- Hash passwords
SELECT similarity('postgresql', 'postgersql'); -- Fuzzy matchingMonitoring & Maintenance
监控与维护
sql
-- Database size and growth
SELECT pg_size_pretty(pg_database_size(current_database())) as db_size;
-- Table and index sizes
SELECT schemaname, tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Index usage statistics
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- Unused indexessql
-- Database size and growth
SELECT pg_size_pretty(pg_database_size(current_database())) as db_size;
-- Table and index sizes
SELECT schemaname, tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Index usage statistics
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0; -- Unused indexesPostgreSQL-Specific Optimization Tips
PostgreSQL专属优化技巧
- Use EXPLAIN (ANALYZE, BUFFERS) for detailed query analysis
- Configure postgresql.conf for your workload (OLTP vs OLAP)
- Use connection pooling (pgbouncer) for high-concurrency applications
- Regular VACUUM and ANALYZE for optimal performance
- Partition large tables using PostgreSQL 10+ declarative partitioning
- Use pg_stat_statements for query performance monitoring
- 使用EXPLAIN (ANALYZE, BUFFERS) 进行详细查询分析
- 配置postgresql.conf 以适配你的工作负载(OLTP vs OLAP)
- 使用连接池(pgbouncer)应对高并发应用
- 定期执行VACUUM和ANALYZE 以保持最佳性能
- 对大表进行分区 使用PostgreSQL 10+的声明式分区
- 使用pg_stat_statements 进行查询性能监控
📊 Monitoring and Maintenance
📊 监控与维护
Query Performance Monitoring
查询性能监控
sql
-- Identify slow queries
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
-- Check index usage
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0;sql
-- Identify slow queries
SELECT query, calls, total_time, mean_time, rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
-- Check index usage
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0;Database Maintenance
数据库维护
- VACUUM and ANALYZE: Regular maintenance for performance
- Index Maintenance: Monitor and rebuild fragmented indexes
- Statistics Updates: Keep query planner statistics current
- Log Analysis: Regular review of PostgreSQL logs
- VACUUM和ANALYZE: 定期维护以保障性能
- 索引维护: 监控并重建碎片化索引
- 统计信息更新: 保持查询规划器统计信息的时效性
- 日志分析: 定期审查PostgreSQL日志
🛠️ Common Query Patterns
🛠️ 常见查询模式
Pagination
分页
sql
-- ❌ BAD: OFFSET for large datasets
SELECT * FROM products ORDER BY id OFFSET 10000 LIMIT 20;
-- ✅ GOOD: Cursor-based pagination
SELECT * FROM products
WHERE id > $last_id
ORDER BY id
LIMIT 20;sql
-- ❌ 不佳:大数据集使用OFFSET
SELECT * FROM products ORDER BY id OFFSET 10000 LIMIT 20;
-- ✅ 推荐:基于游标分页
SELECT * FROM products
WHERE id > $last_id
ORDER BY id
LIMIT 20;Aggregation
聚合
sql
-- ❌ BAD: Inefficient grouping
SELECT user_id, COUNT(*)
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY user_id;
-- ✅ GOOD: Optimized with partial index
CREATE INDEX idx_orders_recent ON orders(user_id)
WHERE order_date >= '2024-01-01';
SELECT user_id, COUNT(*)
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY user_id;sql
-- ❌ 不佳:低效分组
SELECT user_id, COUNT(*)
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY user_id;
-- ✅ 推荐:使用部分索引优化
CREATE INDEX idx_orders_recent ON orders(user_id)
WHERE order_date >= '2024-01-01';
SELECT user_id, COUNT(*)
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY user_id;JSON Queries
JSON查询
sql
-- ❌ BAD: Inefficient JSON querying
SELECT * FROM users WHERE data::text LIKE '%admin%';
-- ✅ GOOD: JSONB operators and GIN index
CREATE INDEX idx_users_data_gin ON users USING gin(data);
SELECT * FROM users WHERE data @> '{"role": "admin"}';sql
-- ❌ 不佳:低效JSON查询
SELECT * FROM users WHERE data::text LIKE '%admin%';
-- ✅ 推荐:使用JSONB操作符和GIN索引
CREATE INDEX idx_users_data_gin ON users USING gin(data);
SELECT * FROM users WHERE data @> '{"role": "admin"}';📋 Optimization Checklist
📋 优化检查清单
Query Analysis
查询分析
- Run EXPLAIN ANALYZE for expensive queries
- Check for sequential scans on large tables
- Verify appropriate join algorithms
- Review WHERE clause selectivity
- Analyze sort and aggregation operations
- 对耗时查询执行EXPLAIN ANALYZE
- 检查大表上的全表扫描
- 验证合适的连接算法
- 审查WHERE子句的选择性
- 分析排序和聚合操作
Index Strategy
索引策略
- Create indexes for frequently queried columns
- Use composite indexes for multi-column searches
- Consider partial indexes for filtered queries
- Remove unused or duplicate indexes
- Monitor index bloat and fragmentation
- 为频繁查询的列创建索引
- 对多列搜索使用复合索引
- 考虑为过滤查询使用部分索引
- 删除未使用或重复的索引
- 监控索引膨胀和碎片化
Security Review
安全审查
- Use parameterized queries exclusively
- Implement proper access controls
- Enable row-level security where needed
- Audit sensitive data access
- Use secure connection methods
- 仅使用参数化查询
- 实施适当的访问控制
- 必要时启用行级安全
- 审计敏感数据访问
- 使用安全连接方式
Performance Monitoring
性能监控
- Set up query performance monitoring
- Configure appropriate log settings
- Monitor connection pool usage
- Track database growth and maintenance needs
- Set up alerting for performance degradation
- 搭建查询性能监控
- 配置合适的日志设置
- 监控连接池使用情况
- 跟踪数据库增长和维护需求
- 为性能下降设置告警
🎯 Optimization Output Format
🎯 优化输出格式
Query Analysis Results
查询分析结果
undefinedundefinedQuery Performance Analysis
查询性能分析
Original Query:
[Original SQL with performance issues]
Issues Identified:
- Sequential scan on large table (Cost: 15000.00)
- Missing index on frequently queried column
- Inefficient join order
Optimized Query:
[Improved SQL with explanations]
Recommended Indexes:
sql
CREATE INDEX idx_table_column ON table(column);Performance Impact: Expected 80% improvement in execution time
undefined原始查询:
[存在性能问题的原始SQL]
发现的问题:
- 大表上的全表扫描(成本:15000.00)
- 频繁查询的列缺少索引
- 低效的连接顺序
优化后的查询:
[带说明的改进版SQL]
推荐索引:
sql
CREATE INDEX idx_table_column ON table(column);性能影响: 预计执行时间提升80%
undefined🚀 Advanced PostgreSQL Features
🚀 PostgreSQL高级功能
Window Functions
窗口函数
sql
-- Running totals and rankings
SELECT
product_id,
order_date,
amount,
SUM(amount) OVER (PARTITION BY product_id ORDER BY order_date) as running_total,
ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY amount DESC) as rank
FROM sales;sql
-- Running totals and rankings
SELECT
product_id,
order_date,
amount,
SUM(amount) OVER (PARTITION BY product_id ORDER BY order_date) as running_total,
ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY amount DESC) as rank
FROM sales;Common Table Expressions (CTEs)
通用表表达式(CTEs)
sql
-- Recursive queries for hierarchical data
WITH RECURSIVE category_tree AS (
SELECT id, name, parent_id, 1 as level
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, ct.level + 1
FROM categories c
JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree ORDER BY level, name;Focus on providing specific, actionable PostgreSQL optimizations that improve query performance, security, and maintainability while leveraging PostgreSQL's advanced features.
sql
-- Recursive queries for hierarchical data
WITH RECURSIVE category_tree AS (
SELECT id, name, parent_id, 1 as level
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, ct.level + 1
FROM categories c
JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree ORDER BY level, name;专注于提供具体、可落地的PostgreSQL优化方案,在利用PostgreSQL高级功能的同时,提升查询性能、安全性和可维护性。