- 开发工具
- 数据库
【免费下载链接】soar
SQL Optimizer And Rewriter
SOAR(SQL Optimizer And Rewriter)是一款由小米数据库团队开发维护的 SQL 优化与改写自动化工具,其整体架构由语法解析器、集成环境、优化建议、重写逻辑、工具集五大模块组成。本文以官方架构文档 doc/structure.md 为主线,结合仓库源码逐一拆解每个模块的设计思路与底层实现,读者可以借此掌握 SOAR 从 SQL 输入到优化建议产出的完整调用链路,以及如何为二次开发或深度使用定位到对应代码位置。
五大模块总览
SOAR 的架构图如下,整个系统呈现一条清晰的流水线:SQL 先经过语法解析与检查,再在集成环境中完成环境准备,随后由优化建议模块产出评审结论,必要时由重写逻辑产出等价改写后的 SQL,最后由工具集负责输出格式化与展示。
围绕这条流水线,doc/structure.md 将 SOAR 拆解为五大模块:
| 模块 | 核心职责 | 对应源码目录 |
|---|---|---|
| 语法解析器 | 将 SQL 解析为抽象语法树并做语法检查 | ast/、advisor/rules.go 中 ERR 规则 |
| 集成环境 | 区分线上/测试环境,提供安全执行与元数据支撑 | database/、common/config.go |
| 优化建议 | 启发式规则、索引优化、EXPLAIN 解读三类建议 | advisor/heuristic.go、advisor/index.go、advisor/explainer.go |
| 重写逻辑 | 数十种常见场景下的 SQL 等价转写 | ast/rewrite.go |
| 工具集 | markdown 转 HTML、SQL 格式化等辅助能力 | common/markdown.go、common/tricks.go |
语法解析和语法检查:三套解析器的可插拔组合
一条 SQL 从文件、标准输入或命令行参数等形式传递给 SOAR 后,首先进入语法解析器。在解析器的选型上,SOAR 采用了"松散、可插拔"的集成方案,而不是自行维护一套庞大的语法解析库,其演进过程分为三步:
- Vitess 语法解析库(首选):项目最初选用 Vitess 的
sqlparser作为主解析库。从源码可见,SOAR 在构造评审对象Query4Audit时,先用sqlparser.Parse(sql)生成 Vitess 抽象语法树,但"vitess 语法解析不上报,以 tidb parser 为主"(见 advisor/rules.go); - TiDB 语法解析器(补充):随着需求增加,部分复杂 SQL 用 Vitess 实现较为吃力,因此引入 TiDB(pingcap/parser)的语法解析器作为补充。
ast.TiParse()会先通过removeIncompatibleWords()预处理 pingcap/parser 不支持的语法,例如剔除ON UPDATE CASCADE、把CREATE TEMPORARY TABLE改写为CREATE TABLE等(见 ast/tidb.go); - MySQL 执行返回结果(方言盲区兜底):两套解析器仍存在盲区,因此 SOAR 又引入 MySQL 真实执行返回结果,作为多版本 SQL 方言的补充,例如对 Vitess 语法错误(ERR.000)、执行错误(ERR.001)与 EXPLAIN 错误(ERR.002)的识别都依赖这一路输入。
在 advisor/rules.go 的规则代号注释中,ERR被明确标注为"特指 MySQL 执行返回的报错信息",这印证了三路解析输入在错误处理层面的分工。
集成环境:线上环境与测试环境的双环境设计
集成环境区分线上环境与测试环境,用于解决不同场景下的 SQL 优化需求:
- 已有表结构的优化场景:从线上环境导出表结构和足够采样数据到测试环境,即可在测试环境放心执行各种高危操作而不用担心数据损坏;
- 全新数据库的验证场景:只需验证数据字典中是否存在优化可能,用户甚至不需要知道线上环境在哪,试错成本极低。
这两个环境在配置结构体Configuration中对应OnlineDSN与TestDSN两个数据源配置,另有一系列开关控制行为(见 common/config.go):
| 配置项 | 含义 |
|---|---|
online-dsn/test-dsn | 线上/测试环境的数据库连接(addr、schema、user、password、disable) |
allow-online-as-test | 允许 Online 环境同时当作 Test 环境使用 |
disable-version-check | 禁用环境检测(不建议开启,可能导致语句执行异常) |
drop-test-temporary | 是否清理 Test 环境产生的临时库表 |
cleanup-test-database | 清理程序异常退出时残余的测试数据库 |
sampling/sampling-condition | 数据采样开关与采样条件 |
profiling/trace/explain | 测试环境执行的 Profiling、Trace 与 Explain 开关 |
从 advisor/index.go 的NewAdvisor()可以看出,索引建议正是同时依赖env.VirtualEnv(测试环境)与database.Connector(线上环境)两个句柄:DDL 语句会先把库表元数据登记进测试环境;遇到USE语句则切换测试环境当前库。关于双环境更完整的组合场景说明,见 集成环境。
优化建议:三类建议的合并输出
目前 SOAR 可提供三类优化建议:基于启发式规则(经验)的建议、基于索引优化算法的建议、以及基于 EXPLAIN 信息的解读。
启发式规则建议
启发式规则的元数据结构由规则代号、危险等级、规则摘要、规则解释、SQL 示例、建议位置、规则函数七部分组成,其定义如下(见 advisor/rules.go):
// Rule 评审规则元数据结构 type Rule struct { Item string `json:"Item"` // 规则代号 Severity string `json:"Severity"` // 危险等级:L[0-8], 数字越大表示级别越高 Summary string `json:"Summary"` // 规则摘要 Content string `json:"Content"` // 规则解释 Case string `json:"Case"` // SQL示例 Position int `json:"Position"` // 建议所处SQL字符位置,默认0表示全局建议 Func func(*Query4Audit) Rule `json:"-"` // 函数名 }每一条 SQL 经过语法解析后会经过数百个启发式规则逐一检查,命中的规则保存在heuristicSuggest变量中传递下去,与其他优化建议合并输出。规则的代号具有明确的缩写语义,例如:
ALI(Alias):ALI.001建议显式使用 AS 关键字声明别名,ALI.002不建议给通配符*设置别名(L8 高危),ALI.003提示别名不要与表或列同名;ARG(Argument):ARG.001不建议使用前项通配符查找(like '%foo'),ARG.002提示没有通配符的 LIKE 等价于等值查询;ALT(Alter):ALT.001提醒修改表默认字符集不会改已有字段字符集,ALT.002建议同一张表多条 ALTER 合并,ALT.003/ALT.004将删除列、删除主外键标记为高危操作;COL、IDX、JOI、SEC、SUB等分别对应列、索引、连接、安全、子查询等维度,完整清单见 advisor/rules.go。
所有启发式规则实现的函数集中在 advisor/heuristic.go(共 4160 行),规则列表保存在 advisor/rules.go(共 1610 行)中。规则函数与规则代号在InitHeuristicRules()中通过 map 绑定,例如RuleImplicitAlias对应ALI.001、RulePrefixLike对应ARG.001。运行时可以通过soar -list-heuristic-rules打印全部规则,用soar -ignore-rules "ALI.001,IDX.*"忽略指定规则(见 doc/cheatsheet.md)。
索引优化
索引优化模块的挑战在于把 DBA 沉淀的经验转化为覆盖全面、逻辑可推导的算法。SOAR 参考了大量前人著作、论文与博客(知识来源汇总在 鸣谢 章节),核心算法依据《Relational Database Index Design and the Optimizers》一书提出的三星索引理论(Three-Star Index):第一颗星选取 WHERE 等值谓词列作为索引首列;第二颗星加入 ORDER BY 列并保持原有顺序;第三颗星将查询涉及的剩余列加入索引以形成覆盖索引(见 advisor/index.go)。
在实现层面,IndexAdvisor结构体(见 advisor/index.go)收集了whereEQ(等值条件列)、whereINEQ(非等值条件列)、groupBy、orderBy、joinCond(跨层级 JOIN 条件)等信息;IndexInfo则输出一条完整索引建议,包含索引名、库名、表名、DDL 语句与列详情。索引优化的详细算法描述见 索引优化。
EXPLAIN 解读
EXPLAIN 信息对新手而言记忆负担极重:SOAR 仅在 EXPLAIN 信息注解一项就编写了约 200 行代码,按平均行长 120 计算,相当于为 DBA 节省了不下 2 万字的记忆量。解读逻辑集中在 advisor/explainer.go,实现上采用"按维度检查、按表聚合建议"的方式:
checkExplainSelectType():按配置的ExplainWarnSelectType匹配SelectType并给出建议;checkExplainAccessType():按配置的ExplainWarnAccessType匹配访问类型(如全表扫描),输出Scalability提示;checkExplainRef():检查Ref列为 NULL 的访问路径;- 对 JSON 格式的 EXPLAIN 结果,会先通过
database.ConvertExplainJSON2Row()转成行格式统一处理。
所有 EXPLAIN 类建议以EXP.XXX作为规则代号。完整的解读逻辑见 EXPLAIN 信息解读。
重写逻辑:从"给建议"到"帮改写"
早期 SOAR 的功能停留在建议层面,初级用户看到建议也不一定会改写。为降低 SQL 优化成本,SOAR 进一步实现了自动 SQL 重写,提供几十种常见场景下的 SQL 等价转写。重写规则定义在 ast/rewrite.go 中,每个规则包含名称、描述、错误示范(Original)、正确示范(Suggest)与改写函数,且规则是有序的,先后顺序不能乱。已内置的改写规则包括:
| 规则名 | 作用 |
|---|---|
dml2select/reg2select | 将 DELETE 等更新请求转换为只读 SELECT,便于执行 EXPLAIN |
star2columns | 为SELECT *补全表的列信息 |
insertcolumns | 为INSERT补全列信息 |
having | 将 HAVING 中的查询条件改写进 WHERE |
orderbynull | 为不需要排序的 GROUP BY 添加ORDER BY NULL |
unionall | 用UNION ALL替代UNION提高查询效率 |
or2in/or2union | 同列 OR 转 IN、不同列 OR 转 UNION |
dmlorderby | 删除 DML 更新操作中无意义的 ORDER BY |
sub2join/join2sub | 子查询与 JOIN 的相互转换 |
distinctstar | 删除对带主键表无意义的DISTINCT * |
standard | SQL 标准化,如关键字转小写 |
规则之间的依赖顺序同样在代码中体现,例如注释明确"把所有跟 or 相关的重写完之后才进行 or 转 union 的重写"。重写功能的完整逻辑见 重写逻辑,运行时可结合 doc/cheatsheet.md 中-rewrite-rules配置项启用或关闭指定规则。
工具集:优化之外的辅助能力
除了 SQL 优化和改写,SOAR 还提供一系列辅助小工具,方便用户使用并美化输出展现形式:
- Markdown 转 HTML 工具:将 markdown 报告转为带样式的 HTML,支持
report-type、report-css、report-javascript、report-title等配置项控制输出风格(见 common/config.go 与 common/markdown.go); - SQL 格式化输出工具:支持 SQL 压缩与美化,相关实现见 ast/pretty.go 与 ast/rewrite.go 中的格式化逻辑;
- 其他实用命令:
-list-heuristic-rules打印全部启发式规则、-list-report-types打印支持的报告格式、-print-config打印配置等。
所有小工具的具体用法都能在 常用命令 中找到,例如最基本的用法:
echo "select title from sakila.film" | ./soar -log-output=soar.log小结:一条 SQL 在 SOAR 中的完整旅程
回顾整个架构,SOAR 的处理流水线可以概括为:SQL 输入 → 三路语法解析(Vitess + TiDB + MySQL 执行结果)→ 集成环境准备(线上/测试 DSN)→ 三类优化建议合并输出(启发式规则 + 索引算法 + EXPLAIN 解读)→ 等价重写 → 工具集美化输出。五大模块各司其职,同时保持了"松散、可插拔"的设计风格——解析器不自己维护,规则以 map 形式注册、以heuristicSuggest传递合并,重写规则有序联动。对于想深入定制规则的开发者,advisor/heuristic.go 与 ast/rewrite.go 是最佳切入点;而对于想快速上手的使用者,常用命令 与 配置文件 文档则提供了完整的操作指引。
- 开发工具
- 数据库
【免费下载链接】soar
SQL Optimizer And Rewriter
相关推荐
Mesop 构建体系深度解析:Bazel 双环境工具链与 Angular/Proto 集成实践
Mesop 构建体系深度解析:Bazel 双环境工具链与 Angular/Proto 集成实践 Mesop 是一个用 Python 快速构建 AI 应用的开源框
前端后端Web框架重构TypeScript条件逻辑:TS-Pattern类型系统深度解析
重构TypeScript条件逻辑:TS Pattern类型系统深度解析 你是否还在为TypeScript中复杂的条件判断代码感到困扰?是否在面对多层嵌套的 if
开发工具TorchTitan CI Docker 镜像构建体系解析:从 build.sh 调度到 conda 环境与 DeepEP 集成
TorchTitan CI Docker 镜像构建体系解析:从 build.sh 调度到 conda 环境与 DeepEP 集成 TorchTitan 的 CI
人工智能大模型预训练分布式训练强化学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考