在数据库运维过程当中,优化 SQL 是 DBA 团队的平常任务。例行 SQL 优化,不只能够提高程序性能,还可以下降线上故障的几率。mysql
目前经常使用的 SQL 优化方式包括但不限于:业务层优化、SQL逻辑优化、索引优化等。其中索引优化一般经过调整索引或新增索引从而达到 SQL 优化的目的。索引优化每每能够在短期内产生很是巨大的效果。若是可以将索引优化转化成工具化、标准化的流程,减小人工介入的工做量,无疑会大大提升DBA的工做效率。git
SQLAdvisor 是由美团点评公司北京DBA团队开发维护的 SQL 优化工具:输入SQL,输出索引优化建议。 它基于 MySQL 原生词法解析,再结合 SQL 中的 where 条件以及字段选择度、聚合条件、多表 Join 关系等最终输出最优的索引优化建议。目前 SQLAdvisor 在公司内部大量使用,较为成熟、稳定。github
如今,咱们很是高兴地将 SQLAdvisor 开源,项目 GitHub 地址:https://github.com/Meituan-Dianping/SQLAdvisor 。咱们已经把相关开发工做全面转到 GitHub 上,开源版本和内部使用版本保持彻底一致。但愿与业内有相似需求的团队,一块儿打造一款优秀的 SQL 优化产品。sql
SQLAdvisor架构流程图:数据库
1
2
3
4
|
sql: SELECT id FROM crm_loan WHERE id_card = '1234567'
cmd: ./sqladvisor -h xx -P xx -u xx -pxx -d xx -q "SELECT id FROM crm_loan WHERE id_card = '1234567'"
SQLAdvisor输出: alter table crm_loan add index idx_id_card(id_card)
|
上述实现时,涉及的函数为:mysql_sql_parse_join(TABLE_LIST join_table) mysql_sql_parse_join(Item join_condition) ,主要流程图以下:运维
- offset = (table_count / 2) > 10W ? 10W : (table_count / 2)
- rand_rows =(table_count / 2) > 1W ? 1W : (table_count / 2)
- 使用select count(1) from (select field from table force index(best_index) order by cl.. desc limit rand_rows) where field_print 获得知足条件的rows。
- cardinality = rows == 0 ? rand_rows : rand_rows / rows;
- 计算完成选择度后,会根据选择度大小,将该条件添加到该表中的备选索引中。
主要涉及的函数为:mysql_sql_parse_field_cardinality_new() 计算选择度。ide
- 涉及到的字段必须来自于同一张表,而且这张表必须是肯定下来的驱动表。
- Group by 优于 Order by, 二者只能同时存在一个。
- Order by 字段的排序方向必须彻底一致,不然丢弃整个 Order by 字段列。
- 当 Order by 条件中包含主键时,若是主键字段为 Order by。 字段列末尾,忽略该主键,不然丢弃整个 Order by 字段列。
- mysql_sql_parse_group() 判断 Group 后的字段是否均来自于同一张表。
- mysql_sql_parse_order() 判断 Order 后的条件是否可使用。
- mysql_sql_parse_group_order_add() 将字段依次按照规则添加到备选索引链表中。