简介
SQLAdvisor是一款开源的SQL优化工具,由美团点评公司的技术工程部DBA团队开发与维护。作为一个分析SQL语句并提出索引优化建议的工具,它基于MySQL原生词法解析,结合SQL中的where条件、字段选择度、聚合条件、多表Join关系等,输出最优的索引优化建议。
SQLAdvisor的使用与操作也相对简单直观。基本的命令行操作帮助可以通过--help参数获取。在实际操作中,使用者仅需将SQL语句作为输入传递给SQLAdvisor,即可接收到工具生成的索引优化建议。这些建议通常包括对现有索引的调整和新索引的创建建议,以提升数据库查询性能。
除了索引优化建议,SQLAdvisor在公司内部得到广泛应用,其开源性质意味着任何开发者或DBA都可以自由地使用甚至改进这个工具。代码托管在GitHub上,既方便了用户的下载和使用,也鼓励了社区的贡献和反馈,形成了积极的开发与维护生态。
SQLAdvisor 的特点
-
基于 MySQL 原生词法解析,充分保证词法解析的性能、准确定以及稳定性;
-
支持常见的 SQL(Insert/Delete/Update/Select);
-
支持多表 Join 并自动逻辑选定驱动表;
-
支持聚合条件 Order by 和 Group by;
-
过滤表中已存在的索引。
SQLAdvisor架构流程图
Join 处理
Join语法分为两种:Join on 和 Join using,并且 Join on 有时会存在 where 条件中。
分析 Join 条件首先会得到一个 nested_join 的 table list,通过判断它的 join_using_fields 字段是否为空来区分 Join on 与 Join using。
生成的 table list 以二叉树的形式进行存储,以后序遍历的方式对二叉树进行遍历。
生成内部解析树时,right Join 会转换成 left Join。
Join 条件会存在当层的叶子节点上,如果左右节点都是叶子节点,会存在右叶子节点。
每一个非叶子节点代表一次 Join 的结果。
上述实现时,涉及的函数为:mysql_sql_parse_join(TABLE_LIST *join_table) mysql_sql_parse_join(Item *join_condition) ,主要流程图如下:
where 处理
主要是提取 SQL 语句的 where 条件。where 条件中一般由 AND 和 OR 连接符进行连接,因为 OR 比较难以处理,所以忽略,只处理 AND 连接符。
由于 where 条件中可以存在 Join 条件,因此需要进行区分。
依次获取 where 条件,当条件中的操作符是 like,如果不是前缀匹配则丢弃这个条件。
根据条件计算字段的区分度按照高低进行倒序排,如果小于30则丢弃。同时使用最左原则将 where 条件进行有序排列。
Group 与 Order 处理
Group 字段与 Order 字段能否用上索引,需要满足如下条件:> * 涉及到的字段必须来自于同一张表,并且这张表必须是确定下来的驱动表。> * Group by 优于 Order by, 两者只能同时存在一个。> * Order by 字段的排序方向必须完全一致,否则丢弃整个 Order by 字段列。> * 当 Order by 条件中包含主键时,如果主键字段为 Order by。字段列末尾,忽略该主键,否则丢弃整个 Order by 字段列。
整个索引列排序优先级:等值>(group by | order by )> 非等值。
该过程中设计的函数主要有:> * mysql_sql_parse_group() 判断 Group 后的字段是否均来自于同一张表。> * mysql_sql_parse_order() 判断 Order 后的条件是否可以使用。> * mysql_sql_parse_group_order_add() 将字段依次按照规则添加到备选索引链表中。
输出建议
通过上述步骤,已经将每张表的备选索引键全部保存。此时,只要判断每张表中的候选索引键是否在实际表中已存在。没有索引,则给出建议增加对应的索引。
该步骤涉及的函数是:print_index() ,主要的流程图为:
相关链接
开源地址:https://github.com/Meituan-Dianping/SQLAdvisor