mcpField
S
sql-query-optimization

sql-query-optimization

github.com/secondsky数据与数据库240160 次安装5 周前更新
代码仓库

关于 sql-query-optimization

sql-query-optimization 技能汇集 PostgreSQL 和 MySQL 的 SQL 性能分析与优化指导,面向开发者和数据库维护人员。内容涵盖执行计划、索引、查询改写、监控及常见问题排查。

主要功能

  1. 01使用 EXPLAIN 分析执行计划
  2. 02设计与选择索引
  3. 03改写低效查询
  4. 04监控慢查询与性能
  5. 05排查常见 SQL 性能问题

适用场景

  1. 01定位生产环境中的慢查询
  2. 02优化大型表上的筛选与 JOIN
  3. 03改进大结果集的分页
  4. 04批量操作后更新统计信息

安装

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

$npx skills add https://github.com/secondsky/claude-skills --skill sql-query-optimization

安装后在 Claude Code 中输入/sql-query-optimization确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
error-catalog.md
explain-analysis.md
index-strategies.md
optimization-workflow.md
performance-monitoring.md
query-rewrites.md
templates/
explain-query.sql
index-examples.sql
monitoring-queries.sql
query-rewrites.sql

详细介绍

SQL 查询优化

状态:已可用于生产环境 ✅ 最后更新:2025-12-15 最新版本:PostgreSQL 17、MySQL 8.4 依赖项:无


快速入门(10 分钟)

1. 找出慢查询
-- PostgreSQL: Enable pg_stat_statements
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- Find slowest queries
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
2. 使用 EXPLAIN 分析
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT * FROM orders WHERE user_id = 123;

-- Look for:
-- - Seq Scan on large tables → needs index
-- - High "Rows Removed by Filter" → poor selectivity
-- - Temp read/written → increase work_mem
3. 创建索引
-- Add missing index
CREATE INDEX CONCURRENTLY idx_orders_user
ON orders(user_id);

-- Verify improvement
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE user_id = 123;
-- Execution time should drop 10-100x

关键规则

务必做到 ✓
规则原因示例
为外键创建索引JOIN 需要对列建立索引CREATE INDEX idx_orders_user ON orders(user_id)
在生产环境部署前使用 EXPLAIN ANALYZE验证查询计划是否最优EXPLAIN (ANALYZE, BUFFERS) <query>
仅选择特定列减少 90% 的数据传输使用 SELECT id, name FROM users,而不是 SELECT *
为无上限的查询添加 LIMIT防止内存耗尽SELECT * FROM logs ORDER BY id LIMIT 100
使用预处理语句防止 SQL 注入并提升速度db.query('SELECT * FROM users WHERE id = $1', [id])
批量操作后运行 ANALYZE更新查询规划器统计信息ANALYZE table_name
监控 pg_stat_statements持续跟踪查询性能每天检查是否出现性能退化
使用连接池将连接开销降低 10 倍new Pool({ max: 20 })
绝不这样做 ✗
反模式问题修复方法
在生产环境中使用 SELECT *获取不必要的列仅选择特定列
LIKE '%term%' 中使用前导通配符无法使用索引改用全文搜索
通过字符串拼接构造 SQL存在 SQL 注入漏洞使用参数化查询
大量结果不加 LIMIT内存耗尽始终添加 LIMIT 和分页
在循环中执行 N+1 查询网络延迟 × N使用 JOIN 或批量加载
忽略 EXPLAIN 输出将慢查询部署到生产环境部署前务必使用 EXPLAIN
在循环中执行多次 INSERT批量操作速度慢使用包含多个 VALUES 的批量 INSERT
使用 OFFSET 分页O(n) 时间复杂度,且会扫描被跳过的行使用基于游标的分页

7 个关键错误

1. 大表上的顺序扫描

症状:在 100 万行以上的表上出现 Seq Scan on orders (cost=0.00..150000.00) 原因:筛选列上没有索引 修复方法:CREATE INDEX idx_orders_column ON orders(column) 影响:速度提升 10–100 倍

2. 外键缺少索引

症状:JOIN 速度慢(5 秒以上) 原因:外键列没有建立索引 修复方法:CREATE INDEX idx_orders_user_id ON orders(user_id) 影响:JOIN 速度提升 50–500 倍

3. N+1 查询问题

症状:N 条记录执行 1 + N 次查询 原因:循环中 ORM 延迟加载 修复方法:使用 JOIN 或预加载:SELECT u.*, o.* FROM users u LEFT JOIN orders o ON u.id = o.user_id 影响:N 次查询 → 1 次查询

4. LIKE 中使用前导通配符

症状:WHERE name LIKE '%search%' 触发顺序扫描 原因:索引无法匹配字符串中间部分 修复方法:使用全文搜索(GIN 索引)或三元组 影响:速度提升 100–1000 倍

5. 在生产环境中使用 SELECT *

症状:网络流量高、响应慢 原因:获取全部 50 列,而实际只需要 3 列 修复方法:SELECT id, name, email(显式列出列名) 影响:数据传输量减少 90%

6. 大量结果缺少 LIMIT

症状:服务器内存耗尽、查询超时 原因:尝试返回 500 万行 修复方法:SELECT * FROM logs WHERE ... LIMIT 100,并添加分页 影响:内存使用量保持恒定

7. 批量加载后统计信息过时

症状:即使有索引,也选择了错误的查询计划 原因:PostgreSQL 统计信息已过时 修复方法:批量操作后运行 ANALYZE table_name 影响:正确选择查询计划

所有 12 个错误及详细解决方案,请参阅 references/error-catalog.md。


常见模式摘要

模式使用场景示例性能
B-Tree 索引等值、范围和排序查询CREATE INDEX idx ON t(col)默认选择,通用性最佳
复合索引多列 WHERE 子句CREATE INDEX idx ON t(c1, c2)比单列索引快 5-50 倍
覆盖索引包含所有查询列CREATE INDEX idx ON t(c1) INCLUDE (c2)快 2-10 倍(无需访问堆)
部分索引筛选部分行CREATE INDEX idx ON t(c) WHERE status='active'索引体积减少 50-90%
JOIN 重写替换 IN 子查询INNER JOIN users u ON o.user_id = u.id比子查询快 5-20 倍
批量 INSERT批量加载数据INSERT INTO t VALUES (..),(..)比逐条插入快 10-100 倍
游标分页提升大偏移量查询的性能WHERE id > last_id LIMIT 100时间复杂度为 O(1),而非 O(n)

配置摘要

PostgreSQL 配置
-- Increase work_mem for complex queries (reloadable - no restart needed)
SET work_mem = '256MB';

-- Increase shared_buffers for better caching (25% of RAM)
ALTER SYSTEM SET shared_buffers = '8GB';

-- IMPORTANT: shared_buffers requires a full PostgreSQL server restart!
-- This setting is NOT reloadable via pg_reload_conf()
--
-- To apply shared_buffers change:
-- 1. Stop PostgreSQL:   sudo systemctl stop postgresql
-- 2. Start PostgreSQL:  sudo systemctl start postgresql
-- OR use:              sudo systemctl restart postgresql
--
-- Verify the change took effect:
-- SHOW shared_buffers;

-- Enable auto-vacuum (reloadable - can use pg_reload_conf)
ALTER SYSTEM SET autovacuum = on;

-- Reload config (ONLY works for parameters that don't require restart)
-- This will NOT reload shared_buffers - restart required for that!
SELECT pg_reload_conf();
MySQL 配置
# my.cnf
[mysqld]
innodb_buffer_pool_size = 8G  # 70% of RAM
max_connections = 500
slow_query_log = 1
long_query_time = 1

何时加载参考资料

性能分析:

  • 在阅读 EXPLAIN 输出、理解查询计划、分析缓冲区统计信息、比较 PostgreSQL 与 MySQL 的 EXPLAIN 时,加载 references/explain-analysis.md
  • 在设置监控、长期跟踪慢查询、监控缓存命中率、识别膨胀表时,加载 references/performance-monitoring.md

索引优化:

  • 在选择索引类型(B-Tree、GIN、GiST、Hash)、创建复合索引、确定列顺序、使用覆盖索引、实现部分索引、监控索引使用情况时,加载 references/index-strategies.md

查询优化:

  • 在重写慢查询、将子查询转换为 JOIN、消除 N+1 查询、实现分页、优化 LIKE 查询、批量执行操作时,加载 references/query-rewrites.md

系统化流程:

  • 在遵循分步优化流程、提出优化假设、衡量改进效果、监控长期性能时,加载 references/optimization-workflow.md

错误排查:

  • 在调试特定错误(顺序扫描、缺少索引、N+1 查询等)、了解根本原因、实施经过验证的解决方案时,加载 references/error-catalog.md

使用捆绑资源

模板(复制粘贴 SQL)
# EXPLAIN query templates
templates/explain-query.sql

# Index creation patterns
templates/index-examples.sql

# Query rewrite examples
templates/query-rewrites.sql

# Monitoring queries
templates/monitoring-queries.sql
参考资料(深入探讨)
# Comprehensive guides
references/error-catalog.md              # All 12 errors + solutions
references/explain-analysis.md           # Reading query plans
references/index-strategies.md           # Index types & selection
references/query-rewrites.md             # Before/after optimizations
references/performance-monitoring.md     # Long-term monitoring
references/optimization-workflow.md      # Systematic process

依赖项

PostgreSQL 扩展:

  • pg_stat_statements - 查询性能跟踪(内置)
  • pg_trgm - 三元组相似度搜索(可选,用于模糊匹配)

MySQL:

  • performance_schema - 性能监控(在 8.0+ 中默认启用)

无需其他依赖项。


预防已知问题

问题症状预防措施
顺序扫描对 1M+ 行执行 Seq Scan在上线前为筛选列创建索引
缺少 FK 索引JOIN 缓慢始终为外键创建索引
N+1 查询1+N 次数据库调用使用 JOIN 或预加载
前导通配符LIKE '%x%' 查询缓慢使用全文搜索(GIN)
SELECT * 导致膨胀网络流量高仅选择特定列
没有 LIMIT内存耗尽始终为无界查询添加 LIMIT
统计信息过时查询计划错误批量操作后运行 ANALYZE
索引顺序错误索引存在但未使用匹配查询模式
缺少复合索引多个 WHERE 条件查询缓慢创建复合索引
没有连接池延迟高实施连接池(20-50 个连接)
SQL 注入安全漏洞仅使用预处理语句
临时数据溢写排序时发生磁盘 I/O增大 work_mem

完整设置清单

生产环境部署:

  • 启用 pg_stat_statements 或 performance_schema
  • 为所有外键列创建索引
  • 为 WHERE、JOIN、ORDER BY 子句中的列创建索引
  • 将 SELECT * 替换为指定列
  • 为所有无界查询添加 LIMIT
  • 使用预处理语句(参数化查询)
  • 实施连接池(20-50 个连接)
  • 配置 work_mem(每个连接 256MB-1GB)
  • 配置 shared_buffers(PostgreSQL 使用 RAM 的 25%)
  • 启用慢查询日志记录(阈值:100-1000ms)
  • 对所有关键查询运行 EXPLAIN ANALYZE
  • 设置 pg_stat_statements 的每日监控
  • 在每晚批量操作后安排 ANALYZE
  • 监控缓存命中率(目标:>99%)
  • 每月检查并删除未使用的索引

生产环境示例

优化前:

-- Query: Fetch user orders
SELECT * FROM orders WHERE user_id = 123;

-- Performance:
-- Execution time: 2500ms
-- Seq Scan on orders (1M rows scanned)
-- Network: 50MB transferred
-- No index on user_id

优化后:

-- Add index
CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders(user_id);

-- Optimize query
SELECT id, total, status, created_at
FROM orders
WHERE user_id = 123
LIMIT 100;

-- Performance:
-- Execution time: 12ms (208x faster!)
-- Index Scan using idx_orders_user_id (100 rows)
-- Network: 50KB transferred (1000x less!)
-- Covering index with INCLUDE

结果:执行速度提升 208 倍,数据传输量减少 1000 倍


如需全面的优化指导、错误解决方案和生产环境模式,请加载上方“何时加载参考资料”中列出的适当参考文件。

评论

支持 Markdown