首页 > 数据库 >SQL优化工具SQLAdvisor工作原理介绍

SQL优化工具SQLAdvisor工作原理介绍

时间:2024-12-12 15:58:56浏览次数:6  
标签:Join where SQLAdvisor 索引 SQL table 优化

在数据库运维过程中,优化 SQL 是 DBA 团队的日常任务。例行 SQL 优化,不仅可以提升程序性能,还能够降低线上故障的概率。

目前常用的 SQL 优化方式包括但不限于:业务层优化、SQL逻辑优化、索引优化等。其中索引优化通常通过调整索引或新增索引从而达到 SQL 优化的目的。索引优化往往可以在短时间内产生非常巨大的效果。如果能够将索引优化转化成工具化、标准化的流程,减少人工介入的工作量,无疑会大大提高DBA的工作效率。

SQLAdvisor 是由美团点评公司北京DBA团队开发维护的 SQL 优化工具:输入SQL,输出索引优化建议。 它基于 MySQL 原生词法解析,再结合 SQL 中的 where 条件以及字段选择度、聚合条件、多表 Join 关系等最终输出最优的索引优化建议。目前 SQLAdvisor 在公司内部大量使用,较为成熟、稳定。

现在,我们非常高兴地将 SQLAdvisor 开源,项目 GitHub 地址:https://github.com/Meituan-Dianping/SQLAdvisor 。我们已经把相关开发工作全面转到 GitHub 上,开源版本和内部使用版本保持完全一致。希望与业内有类似需求的团队,一起打造一款优秀的 SQL 优化产品。

SQLAdvisor架构流程图SQLAdvisor处理流程

SQLAdvisor处理流程

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)   

SQLAdvisor快速入门教程

  • 基于 MySQL 原生词法解析,充分保证词法解析的性能、准确定以及稳定性;
  • 支持常见的 SQL(Insert/Delete/Update/Select);
  • 支持多表 Join 并自动逻辑选定驱动表;
  • 支持聚合条件 Order by 和 Group by;
  • 过滤表中已存在的索引。

Join 处理

  1. Join语法分为两种:Join on 和 Join using,并且 Join on 有时会存在 where 条件中。
  2. 分析 Join 条件首先会得到一个 nested_join 的 table list,通过判断它的 join_using_fields 字段是否为空来区分 Join on 与 Join using。
  3. 生成的 table list 以二叉树的形式进行存储,以后序遍历的方式对二叉树进行遍历。
  4. 生成内部解析树时,right Join 会转换成 left Join。
  5. Join 条件会存在当层的叶子节点上,如果左右节点都是叶子节点,会存在右叶子节点。
  6. 每一个非叶子节点代表一次 Join 的结果。

上述实现时,涉及的函数为:mysql_sql_parse_join(TABLE_LIST *join_table) mysql_sql_parse_join(Item *join_condition) ,主要流程图如下:join流程

join流程

where 处理

  1. 主要是提取 SQL 语句的 where 条件。where 条件中一般由 AND 和 OR 连接符进行连接,因为 OR 比较难以处理,所以忽略,只处理 AND 连接符。
  2. 由于 where 条件中可以存在 Join 条件,因此需要进行区分。
  3. 依次获取 where 条件,当条件中的操作符是 like,如果不是前缀匹配则丢弃这个条件。
  4. 根据条件计算字段的区分度按照高低进行倒序排,如果小于30则丢弃。同时使用最左原则将 where 条件进行有序排列。

计算区分度

  1. 通过 “show table status like” 获得表的总行数 table_count。
  2. 通过计算选择表中已存在的区分度最高的索引 best_index,同时Primary key > Unique key > 一般索引。
  3. 通过计算获取数据采样的起始值offset与采样范围rand_rows: > * 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() 计算选择度。计算区分度流程

计算区分度流程

添加备选索引

  1. mysql_sql_parse_index()将条件按照选择度添加到备选索引链表中。

  2. 上述两函数的流程图如下所示:

    添加备选索引

Group 与 Order 处理

  1. Group 字段与 Order 字段能否用上索引,需要满足如下条件: > * 涉及到的字段必须来自于同一张表,并且这张表必须是确定下来的驱动表。 > * Group by 优于 Order by, 两者只能同时存在一个。 > * Order by 字段的排序方向必须完全一致,否则丢弃整个 Order by 字段列。 > * 当 Order by 条件中包含主键时,如果主键字段为 Order by。 字段列末尾,忽略该主键,否则丢弃整个 Order by 字段列。

  2. 整个索引列排序优先级:等值>(group by | order by )> 非等值。

  3. 该过程中设计的函数主要有: > * mysql_sql_parse_group() 判断 Group 后的字段是否均来自于同一张表。 > * mysql_sql_parse_order() 判断 Order 后的条件是否可以使用。 > * mysql_sql_parse_group_order_add() 将字段依次按照规则添加到备选索引链表中。

    添加group

处理group

处理group

驱动表选择

  1. 经过前期的 where 解析、Join 解析,已经将 SQL 中表关联关系存储起来,并且按照一定逻辑将候选驱动表确定下来。
  2. 在侯选驱动表中,按照每一张表的侯选索引字段中第一个字段进行计算表中结果集大小。
  3. 使用 explain select * from table where field 来计算表中结果集。
  4. 结果集小最小的被确为驱动表。
  5. 步骤中涉及的函数为:final_table_drived(),在该函数中,调用了函数 get_join_table_result_set() 来获取每张驱动候选表的行数。

添加被驱动表备选索引

  1. 通过上述过程,已经选择了驱动表,也通过解析保存了语句中的条件。

  2. 由于选定了驱动表,因此需要对被驱动表的索引,根据 Join 条件进行添加。

  3. 该过程涉及的函数主要是:mysql_index_add_condition_field(),流程如下:

    驱动表选择

输出建议

  1. 通过上述步骤,已经将每张表的备选索引键全部保存。此时,只要判断每张表中的候选索引键是否在实际表中已存在。没有索引,则给出建议增加对应的索引。

  2. 该步骤涉及的函数是:print_index() ,主要的流程图为:

    驱动表选择

  • Functionality Added or Changed
    • 调整架构将 SQLParser 与 SQLAdvisor 模块隔离,方便调试。
    • 重新架构多表 Join 关系的 find_join_elements() 函数,思路更加清晰。
    • 修改选定驱动表的策略,确保驱动表为小结果集。
    • 添加 where 条件中的 like 处理。
    • 优化 Order by 逻辑,忽略 Order by primary key 场景。
    • 输出索引建议前,增加判断索引是否已存在。
  • Bugs Fixed
    • 修复 SQL 无法处理中文问题。
    • 修复字段多次出现在 where 条件中从而导致多次出现在索引列中问题。
    • 修复在 find_best_index() 函数中,对 MySQL API 中的 result 对象提前 free,导致指针失效问题。

和各位同行共同打造一款企业级优秀的 SQL 优化产品,希望大家能够积极参与。 欢迎大家将需求或发现的 Bug 在 Github 上提交 issue,帮助 SQLAdvisor 逐渐壮大;也欢迎大家在 SQLAdvisor 用户交流群(QQ: 231434335)相互交流,共同学习。

  1. SQLAdvisor快速入门教程.
  2. SQLAdvisor原理和架构.
  3. SQLAdvisor release notes.
  4. SQLAdvisor开发规范.
  5. FAQ.

links:

美团点评SQL优化工具SQLAdvisor开源 - 美团技术团队

标签:Join,where,SQLAdvisor,索引,SQL,table,优化
From: https://blog.csdn.net/a772304419/article/details/144373712

相关文章

  • MySQL原理解析:MySQL的索引结构为什么使用B+树?
    前言在MySQL中,无论是Innodb还是MyIsam,都使用了B+树作索引结构(这里不考虑hash等其他索引)。本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明MySQL为什么选择B+树作为索引结构。一、二叉查找树(BST):不平衡二叉查找树(BST,BinarySearchTree......
  • 转载:【AI系统】AI 编译器后端优化
    AI编译器分为多层架构,最顶层由各种AI训练框架编写的神经网络模型架构,一般由Python编写,常见的AI训练框架有PyTorch、MindSpore、PaddlePaddle等。在导入AI编译器时需要用对应框架的converter功能转换为AI编译器统一的GraphIR,并在计算图级别由GraphOptimizer进......
  • SQL语句 关键字执行顺序
    SQL语句关键字执行顺序在MySQL中,查询的执行顺序并不是严格按照SQL语句中各子句的书写顺序来执行的。实际上,SQL查询的逻辑处理顺序是这样的:FROM:从表或视图中选择数据源。WHERE:对数据源中的行进行筛选,只保留符合条件的行。GROUPBY:将结果集按指定列分组。HAVING:对分组后......
  • PG数据库负载高检查慢SQL
    一、查询当前正在执行所有SQL语句``二、判断是否存在慢查询语句``字段解释PID数据库查询进程IDquery_stay查询时长秒query查询SQL语句``三、按查询进程,杀掉慢查询释放资源SELECTpg_terminate_backend(PID);SELECTpg_terminate_backend(6289);......
  • 自定义typeHandler将包含经纬度对象插入到mysql的point类型的字段中
    博客:https://www.emanjusaka.top公众号:emanjusaka的编程栈下面给出关键部分代码,完整代码请访问原文地址mysql中的point类型在java中没有对应的类型匹配,需要我们自定义typeHandler去处理。环境参数SpringBootMybatisPlusmysql代码实现typeHandlerGeomPointTyp......
  • mysql&elasticsearch备份恢复
    目录1.mysql备份1.1.使用mysqldump命令备份整个数据库:1.2.备份特定表:2.恢复MySQL数据库2.1.使用备份文件恢复数据库:3.备份elasticsearch索引3.1.注册本次备份的存储路径3.2.查看当前备份快照信息3.3.备份索引数据4.恢复elasticsearch索引4.1.恢复索......
  • 转载:【AI系统】计算图的优化策略
    除了前面提到的算子替换和算子前移等内容,本文内容将深入探讨计算图的优化策略,我们将细致分析图优化的其他重要内容,如改变数据节点的数据类型或存储格式来提升模型性能,以及优化数据的存储和访问方式以降低内存占用和数据访问时间。以上内容的理解和掌握,对于高效利用计算资源,提升算......
  • CentOS 安装配置使用MySQL教程-----超全手把手教。
    前言CentOS安装MySQL与统信OS、openEuler等类似系统的安装方式几乎一样。可参考下面的步骤进行设置与连接。具体步骤:1.安装MySQL服务器sudoyuminstallmysql-server2.启动MySQL服务sudosystemctlstartmysqld3.运行安全安装向导sudomysql_secure_installa......
  • 一个实例用全创建型模式-优化(冗余消除)
     上一篇:一个实例用全创建型模式-CSDN博客目录:《一个实例讲完23种设计模式》当前:单件+抽象工厂+创建者+工厂方法+优化需求:坦克大战创建两种坦克坦克类型   射程   速度b70   70米   时/70公里b50   50米   时/50公里设计说明1.抽象工......
  • 如何避免易优EyouCms在使用过程中出现“SQLSTATE[HY000]: General error: 1615 Prepar
    在使用易优EyouCms时,为了避免出现“SQLSTATE[HY000]:Generalerror:1615Preparedstatementneedstobere-prepared”的错误,可以采取以下预防措施和优化步骤。这个错误通常是由于数据库配置不当或预处理语句处理不当引起的。以下是详细的解决方案:正确配置数据库参数:使用......