你的数据库查询越来越慢。
表数据量上去了,索引也加了,但查询还是卡。
这时候别盲目加索引。先让 AI 帮你看看执行计划,找到真正的瓶颈在哪。
我最近用 Claude Code + ChatGPT 分析了 5 个真实的慢查询,效果不错。把整个过程整理出来。
案例一:LIKE ‘%关键词%’ 导致全表扫描
原始查询(耗时 28 秒):
SELECT * FROM products
WHERE name LIKE '%耳机%'
OR description LIKE '%耳机%';
问题很明显:LIKE '%xxx%' 没法用索引,数据库只能全表扫描。
AI 给出的优化方案:
-- 方案 A:使用 PostgreSQL 全文搜索
SELECT * FROM products
WHERE to_tsvector('simple', name || ' ' || description)
@@ to_tsquery('simple', '耳机');
-- 方案 B:如果数据量大,建一个搜索专用表
CREATE TABLE product_search (
product_id INTEGER REFERENCES products(id),
search_vector tsvector,
PRIMARY KEY (product_id)
);
-- 插入数据
INSERT INTO product_search (product_id, search_vector)
SELECT id, to_tsvector('simple', name || ' ' || description)
FROM products;
-- 查询
SELECT p.* FROM products p
JOIN product_search ps ON p.id = ps.product_id
WHERE ps.search_vector @@ to_tsquery('简单', '耳机');
优化后查询时间降到 120 毫秒。快了 230 倍。
案例二:嵌套子查询导致的笛卡尔积
原始查询(耗时 45 秒):
SELECT u.name,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) as order_count,
(SELECT SUM(amount) FROM orders o WHERE o.user_id = u.id) as total_spent
FROM users u
WHERE u.created_at > '2025-01-01';
每个用户都要查两次 orders 表,10 万用户就是 20 万次查询。
AI 给出的优化方案:
SELECT u.name,
COALESCE(s.order_count, 0) as order_count,
COALESCE(s.total_spent, 0) as total_spent
FROM users u
LEFT JOIN (
SELECT user_id,
COUNT(*) as order_count,
SUM(amount) as total_spent
FROM orders
GROUP BY user_id
) s ON u.id = s.user_id
WHERE u.created_at > '2025-01-01';
把子查询改成 JOIN,一次性聚合所有数据。查询时间降到 800 毫秒。
关键技巧:GROUP BY 在子查询里做,外层只做 JOIN。这样数据库可以用一次扫描完成聚合。
案例三:没有分页的大列表查询
原始查询(耗时 15 秒):
SELECT * FROM logs ORDER BY created_at DESC LIMIT 10000 OFFSET 50000;
OFFSET 50000 意味着数据库要先查出 50000 条记录,然后丢弃前 50000 条,只返回最后 10000 条。
AI 给出的优化方案:
-- 方案 A:游标分页(推荐)
SELECT * FROM logs
WHERE created_at < '上次最后一条的时间戳'
ORDER BY created_at DESC
LIMIT 100;
-- 方案 B:延迟关联
SELECT l.* FROM logs l
INNER JOIN (
SELECT id FROM logs
ORDER BY created_at DESC
LIMIT 100 OFFSET 50000
) AS sub ON l.id = sub.id;
方案 A 用了游标分页,不需要算 OFFSET。方案 B 先用子查询拿到 ID 列表(只扫索引),再回表拿完整数据。
两个方案都降到 200 毫秒以内。
案例四:多表 JOIN 缺少合适索引
原始查询(耗时 35 秒):
SELECT o.id, o.total, c.name, p.title
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN products p ON o.product_id = p.id
WHERE o.status = 'completed'
AND o.created_at BETWEEN '2025-01-01' AND '2025-12-31'
AND c.country = 'CN';
AI 分析执行计划后的建议:
-- orders 表复合索引
CREATE INDEX idx_orders_status_created ON orders(status, created_at)
INCLUDE (customer_id, product_id, total);
-- customers 表索引
CREATE INDEX idx_customers_country ON customers(country)
INCLUDE (name, id);
注意 INCLUDE 关键字。它创建的是覆盖索引——查询需要的字段都在索引里,不需要回表。
优化后查询时间降到 300 毫秒。
案例五:GROUP BY 后过滤聚合结果
原始查询(耗时 22 秒):
SELECT department, AVG(salary) as avg_salary
FROM employees
WHERE department IN ('技术部', '产品部', '市场部')
GROUP BY department
HAVING AVG(salary) > 15000;
HAVING 在 GROUP BY 之后执行,这意味着先对所有部门分组计算平均值,然后再过滤。
AI 给出的优化方案:
WITH dept_stats AS (
SELECT department, AVG(salary) as avg_salary
FROM employees
WHERE department IN ('技术部', '产品部', '市场部')
GROUP BY department
)
SELECT department, avg_salary
FROM dept_stats
WHERE avg_salary > 15000;
用 CTE 让查询意图更清晰。虽然在这个例子里性能提升不大(CTE 会被内联),但如果逻辑更复杂,CTE 能让数据库优化器更好地选择执行计划。
实际测试中,加上索引后 HAVING 条件也能走索引过滤,查询降到 500 毫秒。
用 AI 分析执行计划的技巧
光知道怎么优化不够,你得会自己发现问题。
方法 1:让 AI 解读 EXPLAIN 输出
把 EXPLAIN ANALYZE 的结果丢给 Claude 或 ChatGPT:
这是 PostgreSQL 的执行计划,帮我分析哪里慢:
Seq Scan on orders (cost=0.00..125000.00 rows=5000000 width=48)
Filter: (status = 'completed' AND created_at >= '2025-01-01')
Rows Removed by Filter: 4500000
...
AI 会告诉你:Seq Scan 说明没走索引,Filter 去掉 450 万行说明选择性差,建议加复合索引。
方法 2:让 AI 自动生成索引建议
-- 把慢查询发给 AI
-- Prompt: "这个查询很慢,请分析并给出索引建议"
SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
JOIN items i ON o.id = i.order_id
WHERE u.city = '北京'
AND o.amount > 100
AND i.category = '电子产品'
ORDER BY o.created_at DESC;
AI 通常会建议:
CREATE INDEX idx_users_city ON users(city) INCLUDE (id);
CREATE INDEX idx_orders_user_amount ON orders(user_id, amount)
INCLUDE (id, created_at);
CREATE INDEX idx_items_order_category ON items(order_id, category)
INCLUDE (id);
方法 3:定期用 AI 审查慢查询日志
把 MySQL 的 slow_query_log 或 PostgreSQL 的 pg_stat_statements 导出成 CSV,让 AI 分析 Top 20 慢查询,批量给出优化建议。
工具推荐
| 工具 | 用途 | 费用 |
|---|---|---|
| Claude Code | 交互式 SQL 优化 | API 按量付费 |
| ChatGPT Plus | 解释执行计划 | $20/月 |
| ExplainSQL.ai | 自动 SQL 优化 | 免费额度有限 |
| Perplexity AI | 搜索最佳实践 | 免费 |
总结
SQL 优化的核心思路就三条:
- 能走索引就别全表扫描
- 能 JOIN 就别子查询
- 能覆盖就别回表
AI 的作用不是替你写 SQL,而是帮你快速理解执行计划、给出优化方向。真正动手改的还是你。
你的数据库有慢查询吗?把执行计划丢给 AI 试试,看看它能发现什么。