SQLAdvisor 实战指南:输入一条SQL,自动拿到索引优化建议
【免费下载链接】SQLAdvisor输入SQL,输出索引优化建议项目地址: https://gitcode.com/gh_mirrors/sq/SQLAdvisor
线上一条慢查询把接口响应拖到几秒钟,打开EXPLAIN却看到满屏的Using filesort,索引到底该加在哪一列?这个问题对新手是玄学,对老手也要靠经验试错。SQLAdvisor 正是为解决这一痛点而来——它是一款由美团点评DBA团队开源的 SQL 索引优化工具,输入 SQL,输出索引优化建议。下文按"困局→原理→部署→实操→避坑"的顺序展开,争取让你一篇文章读完就能在测试库上跑起来。
一、慢查询排查的困局:加索引为什么这么难
索引优化看似简单,实际做起来却有三道坎:
- 强经验依赖:建索引要考虑等值条件、排序字段、关联列,还要掂量字段区分度,新手往往无从下手,老手也要反复比对执行计划。
- 信息不完整:仅凭一条 SQL 看不出字段在整张表里的数据分布,更看不出多表关联时该驱动谁、该被谁驱动。
- 试错成本高:每换一种索引组合就要重新执行计划、对比扫描行数,业务高峰期根本不敢动。
这三个问题凑在一起,索引优化就成了典型的"高耗时、低产出"工作。如果能把它流程化、工具化,DBA 和开发者都能省下大量时间。
二、对症下药:SQLAdvisor 替你做了什么
SQLAdvisor 的思路很直接:把"人肉分析 SQL"变成"程序解析 SQL"。它的差异化价值集中在三点:
- 复用 MySQL 原生解析器:它直接改造自 MySQL 源码,走的是
sql/sql_yacc.yy这一套词法与语法分析,拿到的是一棵标准语法树,而不是简单正则匹配,因此对复杂 SQL 的还原度更高。 - 不只看 where:除提取条件字段外,还会分析多表 Join 关系、
group by/order by聚合排序、字段区分度(cardinality),最终按最左前缀原则拼出建议索引。 - 自动过滤重复建议:输出前会对照
information_schema里已存在的索引做去重,只给出确实值得新增的组合。
上图为 SQLAdvisor 的完整处理链路:从入口解析,到驱动表选择,再到索引建议输出。
三、三十分钟完成部署:拉代码、编译、验证
3.1 环境准备
编译前需要准备好以下依赖(以 CentOS 系为例):
yum install cmake libaio-devel libffi-devel glib2 glib2-devel yum install --enablerepo=Percona56 Percona-Server-shared-56其中Percona-Server-shared-56提供编译必需的libperconaserverclient_r客户端库。若系统里只有libperconaserverclient_r.so.18,需要手动补一条软链接指向不带版本号的文件名。
3.2 编译 SQLAdvisor
git clone https://gitcode.com/gh_mirrors/sq/SQLAdvisor cd SQLAdvisor cmake -DBUILD_CONFIG=mysql_release -DCMAKE_BUILD_TYPE=debug \ -DCMAKE_INSTALL_PREFIX=/usr/local/sqlparser ./ make && make install cd sqladvisor/ cmake -DCMAKE_BUILD_TYPE=debug ./ make第一次cmake负责编译底层的sqlparser解析库并安装到/usr/local/sqlparser;第二次则只编译sqladvisor/目录,最终在该目录下生成可执行文件sqladvisor。更完整的步骤可参考官方文档 doc/QUICK_START.md。
3.3 验证是否成功
./sqladvisor --help能看到参数说明即代表部署成功。两个高频报错提前预警:一是 glib 头文件路径找不到,需按实际安装位置修改sqladvisor/CMakeLists.txt里的include_directories;二是链接阶段报perconaserverclient_r缺失,多半就是软链接没配好。
四、读懂工作机理:一条 SQL 的四站旅程
不贴源码,用流程理解它内部是怎么思考的。
4.1 第一站:解析,把 SQL 拆成关系网
解析阶段先处理 where 段和 Join 段。where 条件里只认AND连接的等值判断与前缀匹配的LIKE,OR和子查询会被直接忽略;Join 条件则以二叉树结构存储,后序遍历还原各表关联,且right join在内部会被转成left join统一处理。
Join 解析是后续驱动表判定的基础,图中展示了条件类型判断与关联关系的落库方式。
4.2 第二站:区分度,决定谁站队首
区分度越高,越适合放在索引前缀。SQLAdvisor 先通过show table status拿到表总行数,再挑出表内已有的最优索引(主键 > 唯一键 > 普通索引)做采样,计算"满足条件的行数 / 采样行数"作为区分度,低于 30 的字段直接弃用,剩余的按区分度倒序进入备选队列。
区分度(cardinality)计算依赖真实数据采样,因此工具必须能连上目标库。
4.3 第三站:驱动表,谁的结果集小谁先跑
多表查询必须先定驱动表:工具对每张候选表按其第一个索引字段预估结果集大小,选择结果集最小的表作为驱动表,再依据 Join 条件为被驱动表补充索引。group by/order by字段只有在全部来自驱动表时才被采纳,且group by优先级高于order by,排序方向必须完全一致,否则整组丢弃。
驱动表确认后,剩余表的索引建议才真正落定。
4.4 第四站:输出,去重后给出建议
每张表的备选索引列最终汇总,与线上已有索引比对,剔除重复组合后输出建议语句。整个排序优先级可概括为:等值 > group/order > 非等值。理论细节见官方文档 doc/THEORY_PRACTICES.md。
五、两种调用姿势:命令行与配置文件
5.1 命令行直传
./sqladvisor -h 127.0.0.1 -P 3306 -u root -p 'yourpass' \ -d testdb -q "select * from t_order where user_id=100 and create_time>'2023-01-01'" -v 1注意两点:参数名与值之间必须用空格分隔;SQL 中出现双引号、反引号时要加\转义,否则解析会报错。
5.2 配置文件批量执行
cat > sql.cnf <<EOF [sqladvisor] username=root password=yourpass host=127.0.0.1 port=3306 dbname=testdb sqls=sql1;sql2;sql3 EOF ./sqladvisor -f sql.cnf -v 1官方建议优先使用配置文件方式,既能规避转义问题,也便于把多条 SQL 用分号拼接后一次性分析。
六、适用场景与避坑清单
值得用的场景:
- 从慢查询日志里捞出 TOP N 语句,批量过一遍找索引缺口;
- 新功能上线前的 SQL 性能评审,替代人工逐条
EXPLAIN; - 周期性巡检,把"加不加索引"从经验判断变成标准动作。
务必记住的坑:
- 目前只支持 MySQL 系数据库,且工具需要直连目标库读取统计信息;
- 含
OR、子查询、函数包裹字段的条件会被静默忽略,结果里不会出现相关建议,别误以为工具"漏了"; - 建议仍属"参考值":落地前务必用
EXPLAIN复核扫描行数,结合真实数据分布再决定是否执行。官方 FAQ(doc/FAQ.md)对支持范围有明确说明。
七、写在最后:把索引建议从"拍脑袋"变成"流水线"
SQLAdvisor 的价值不在于替代 DBA,而在于把最费时间的"判断该不该加索引"自动完成,让专业人员把精力留给真正复杂的优化场景。如果你已经在维护慢查询平台,完全可以把它接入自动化流程:慢日志采集 → SQLAdvisor 批量分析 → 人工复核 → 变更上线。工具虽小,却正好补齐了索引优化这条流水线上最枯燥的一环。
【免费下载链接】SQLAdvisor输入SQL,输出索引优化建议项目地址: https://gitcode.com/gh_mirrors/sq/SQLAdvisor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考