seekdb-sql-review
一个只依赖文本输入的 SQL 与表结构审查技能:不需要连接数据库,也能给出结构化、可复核的优化建议;若能提供执行计划或表结构,结论会显著更准。
1. 适用场景
- 慢查询排查:给出 SQL + 表结构(+
EXPLAIN结果更佳),要定位慢在哪。 - 索引评审:判断某条查询需要什么索引、现有索引是否冗余、联合索引顺序是否正确。
- DDL 上线评审:评估加列、改类型、加索引、改主键对线上写入和锁的影响。
- 并发与事务评审:批量 UPDATE/DELETE 的锁范围、长事务风险、死锁可能性。
不适用:需要真实数据才能回答的容量规划、跨库数据一致性问题、非 MySQL 协议数据库的专有语法。
2. 输入整理
先把用户给的信息整理成四类,缺哪类就在结论里标注「未提供,结论按假设给出」:
| 类别 | 内容 |
| --- | --- |
| 语句 | 完整的 SQL(含参数占位符含义,如 ? 代表什么) |
| 结构 | 相关表的建表语句或列、类型、主键、索引定义 |
| 计划 | EXPLAIN / EXPLAIN ANALYZE 输出(可选但优先级最高) |
| 语境 | 表量级、单次返回行数、调用频率、是否在事务内、读写比例 |
硬性要求:不要凭空编造表结构、索引名或行数。缺失的信息要么问,要么在建议里写成「若表上已有 X 索引则…」。
3. 审查顺序
按「先看计划,再看索引,再看数据分布,最后看语义」的顺序走,避免一上来就给索引建议。
- 执行计划:全表扫描(type=ALL)、
Using filesort、Using temporary、预估行数与实际行数偏差超过一个数量级,都记为问题点。有EXPLAIN ANALYZE时以实际耗时为唯一依据。 - 索引匹配:按「等值列 → 范围列 → 排序列」的联合索引最左前缀规则,判断现有索引能否覆盖 WHERE、ORDER BY、GROUP BY。区分「能过滤」和「能覆盖」(
Using index才算覆盖)。 - 数据分布:区分度低的列(性别、状态位)放联合索引前面通常无效;大表上的
LIKE '%x%'、函数包裹列(WHERE DATE(create_time) = ?)会让索引失效,给出改写形式。 - 语义与规模:
SELECT *、无LIMIT的分页、OR跨列、子查询能否改 JOIN、深分页能否改游标分页。最后才谈 SQL 改写。
4. 输出格式
先给一句结论(「慢在 X,预计可降到 Y 量级」),再给表格:
| # | 问题 | 位置 | 风险 | 建议 | 依据 |
| --- | --- | --- | --- | --- | --- |
| 1 | 联合索引顺序与过滤条件不匹配 | WHERE a=? AND b>? | 高 | 建 (a, b) 或把 b 放最后 | type=ALL,扫描 120 万行 |
风险分三档:高(会导致全表扫描 / 锁全表 / 结果错误)、中(数据量增长后劣化)、低(可读性或微优化)。每条建议都要能对应到具体的语句或列,不能只写「建议加索引」。
涉及 DDL 的建议,补一段可执行语句与回滚方式:
-- 在线加索引,避免长时间锁表
ALTER TABLE orders ADD INDEX idx_user_ctime (user_id, create_time), ALGORITHM=INPLACE, LOCK=NONE;
-- 回滚
ALTER TABLE orders DROP INDEX idx_user_ctime;
5. 常见错误与正确写法
- 索引失效:
WHERE DATE(create_time) = '2026-10-01'→WHERE create_time >= '2026-10-01' AND create_time < '2026-10-02'。 - 联合索引顺序:等值条件在前、范围条件在后;只为高频、区分度高的查询建索引,避免给每列各建单列索引。
- 深分页:
LIMIT 1000000, 20→ 记住上一页末位键做游标分页(WHERE id > ? ORDER BY id LIMIT 20),或先查主键再回表。 - 批量写入:大事务拆成小批次(每批 500~2000 行),既能缩短锁持有时间,也能降低主从延迟。
- 隐式类型转换:字符串列传数字、或列与参数字符集不一致,都会让索引失效,显式统一类型。
- 统计信息陈旧:
EXPLAIN预估行数明显失真时,先更新统计信息再评估计划,不要据此直接加索引。
6. 边界与约束
- 只基于用户提供的材料推断;关键前提缺失时先列出假设,再给条件化结论。
- 不给出需要 DBA 权限才能验证的「一定更快」承诺,改用「预计」「需用
EXPLAIN ANALYZE复核」表述。 - 涉及删除或改主键等破坏性操作时,明确提示备份与灰度顺序,不提供未经确认的直接执行脚本。
- 用户使用中文提问就用中文回答;表格列保持固定,便于对照。
Scan to join WeChat group