前言

在日常开发工作中,数据库是常用的数据存储组件,一旦使用了数据库,那慢查询SQL的优化是绕不开的一道坎,本文旨在分享下自己对平时开发工作中进行SQL调优的理解。本文使用的MySQL版本为 8.0.25。

优化的步骤

1.捕获慢查询SQL

可以通过开启MySQL的慢查询日志或通过一些框架本身(如Druid)提供的慢查询日志监控功能来捕获慢查询SQL。

2.使用 explain 分析 SQL

explain 的执行结果包含上面图中的若干字段,重点关注的字段是 type 和 extra。

type取值,从上至下效率越来越高

  • ALL:扫描全表数据行
  • index:索引行全扫描
  • range:使用索引进行范围扫描,between、in、>、< 等
  • ref:使用非唯一索引或唯一索引前缀进行扫描,返回索引过滤的数据,可为多条,常出现在关联查询中;如下列sql,其中列 dept_id 上建有普通索引
    select username from t_user inner join t_dept using(dept_id) where t_dept.dept_id = 10;
  • eq_ref:与 ref 类似,区别在于是使用唯一索引进行关联扫描
  • const / system:表示通过索引一次就查询到了相关记录,一般为主键或唯一索引查询,system 为 const 的特殊情况,表中仅有一条数据。

extra取值

  • Using filesort:文件排序,表示MySQL需要通过语句查找所有匹配的行,并保存排序关键字与行指针,再通过对关键字进行排序,并按排序后的顺序检索出对应的行。
  • Using temporary:使用临时表保存中间结果,常见的情况有 使用 distinct 关键字、join 语句中使用 order by、使用 group by 无索引列、order by 与 group by 字段不同、union 子查询等。
  • Using where:未使用上索引,使用 where 条件扫描过滤。
  • Using index:表示使用了索引覆盖,仅从索引中就可以查找到对应的数据,不需要访问表。如果与 Using where 一起出现则表示索引用于查询过滤,还需回表查询出所需数据。
  • Using index condition:5.6版本之后新增的功能,称为索引下推;通过使用索引对存储引擎索引出的数据进行再过滤,减少回表查询的次数。

3.根据执行计划进行优化

根据上述 explain 执行出来的结果,可以从中发现慢查询SQL中的问题。

对于没有走索引的查询,通过添加适当的索引,注意需对照原表上的索引,看看有没有需要合并成联合索引,避免构建过多的索引,占用空间和影响插入/更新的效率。

对于一些有索引的语句,却没有正确走索引进行查询的,则需要进一步分析索引失效的情况,下面列出常见的一些索引失效的场景。

1) 全表扫描代价更低:MySQL通过代价计算,发现使用全表扫描会比索引的代价更低,则会放弃使用索引进行查询。一般情况下这类SQL都是比较简单的,如果作为慢SQL被发现可能是因为数据量过大,可能需要通过其他方式处理。

2) 联合索引最左匹配原则:查询语句 select * from table where index2 = 'xx' 是无法使用上索引 IX(index1, index2),可以考虑转换联合索引顺序或新建一个index2索引(如果该联合索引有被其它语句使用)。

3) where语句中包含or:where语句中需要使用or的情况下,需or相连的所有字段都有索引才行。

4) 索引列上加函数:在查询的索引列上使用内置函数都会让索引失效。

5) 对索引列运算:与使用函数相似,都是会使得索引列值发生变化,从而无法使用索引。

6) 隐式转换:select * from t_user where tel = 123; tel字段是varchar类型,查询中使用数值进行匹配会使得执行时对该值进行类型转换,使得索引失效。

7) 负向查询和is NULL判断可能导致索引失效:负向查询包括 NOT、<>、!>、!<、!= 等。

8) asc和desc混用:select * from t order by a asc, b desc;

9) 范围查询阻断后续字段不能走索引:范围查询包括 >=、<=、>、<、in、between。例:select * from t_user where dept_id = 1 and create_date > '2022-05-04 00:00:00' and position_id = 10; 索引 IX_deptid_createdate_positionid(dept_id, create_date, position_id),在执行查询语句时,字段 position_id 的索引不生效,仅使用了前缀 dept_id。

针对上述索引失效的情况,进行相应的索引变更或是修改对应的SQL语句,使得SQL语句能走上正确的索引。以上是基于经验法则对SQL进行优化,可能会在不同的MySQL版本和不同的数据量的情况下呈现不一样的结果,在实践过程中如果能有生产备份库,可以修改后在备份库使用执行计划查看新改动的SQL是否按预期走索引;没有备份库或者不可直接使用备份库的情况下也应在生产环境跟踪下改动后SQL的执行情况。

4.按预期走了索引的慢SQL

如果SQL按预期走了索引进行查询,但SQL语句依然执行过慢,可能有下面几种情况。

大分页查询:select * from t where a = 1 limit 10000, 10; 在分页查询数据量较大,分页选择靠后的页码时,正常的 limit 语句效率会显著降低,可通过延迟关联的形式提高效率。详见 大数据量 limit 分页优化

超大数据量:对于表中数据量已经特别庞大的情况下,这个时候需要根据业务场景,考虑是否能将较远的历史数据进行归档,然后删除原表中的历史数据,降低原表数据量;有些场景可聚合业务数据,把对原表的查询转而查询聚合表;有字符串查询的场景可以考虑使用ES进行检索;如果业务量确实很大,可以考虑使用分库分表。

复杂SQL:对于这类SQL,一般而言是统计类型的查询,可以看看业务上是否可允许进行定期统计并以输出报表记录的形式;如果业务上本身就存在这么复杂的查询,就不建议使用SQL,可采用其他的形式进行解决,如ES等。

MySQL慢SQL调优相关推荐

  1. Mysql排序添加名词_记面试中问到的MySQL的SQL调优问题

    目录 1.场景还原 2.名词解释 3.实践情况 4.个人观点 5.引申问题 1.场景还原 面试官:小伙子,听说你会SQL调优,那我这里有一条SQL,你来帮我调优一下.SQL如下: SELECT * F ...

  2. 记面试中问到的MySQL的SQL调优问题

    目录 1.场景还原 2.名词解释 3.实践情况 4.个人观点 5.引申问题 1.场景还原 面试官:小伙子,听说你会SQL调优,那我这里有一条SQL,你来帮我调优一下.SQL如下: SELECT * F ...

  3. MYSQL 之 SQL 调优

    SQL 调优 不适用子查询 SELECT * FROM t1 WHERE id (SELECT id FROM t2 WHERE name='hechunyang'); 子查询在 MYSQL5.5 版 ...

  4. 【MySQL】sql调优实战教学

    如何定位并优化慢查询Sql? 具体场景具体分析只提出大致思路,其实这个问题属于开放性的题目,主要考察有没有做过SQL优化,由于该问题属于经验的问题,做过了就是做过了没做过就是没做过,问了你就知道是没有 ...

  5. mysql 常用sql调优_MySQL 常用SQL优化

    MySQL 常用SQL优化: 一.大批量插入数据: 1.对于load MyISAM存储引擎的表,可以通过关闭打开MyISAM表非唯一索引的更新来提升导入速度: 例:mysql > alter t ...

  6. Mysql高级调优篇——第五章:Sql调优在面试中深度剖析

    上节讲了Sql调优实战,本章聊聊面试中Sql调优深度的剖析场景! 在讲之前我们先做一些准备工作,建立一些需要用到的表: Mysql高级调优篇表补充--建表SQL_风清扬逍遥子的博客-CSDN博客⭐️t ...

  7. MySQL 索引和 SQL 调优手册

    MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree ...

  8. MySQL索引和SQL调优手册

    MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等. 为了避免混乱,本文将只关注于BTre ...

  9. MySql查询优化性能调优,sql性能自测方法,及Mysql索引介绍

    MySql查询优化性能调优,sql性能自测方法,及Mysql索引介绍 前言 一.普通优化加索引(适用于where条件后一个查询条件) 二.组合查询加索引(适用于where条件后多个查询条件) 三.My ...

最新文章

  1. 【转载】linux服务器下非root权限安装anaconda
  2. 安居客检测到网页抓取_安居客天津租房情况分析
  3. option:contains后面加变量_什么是配置环境变量,配置以后有什么作用呢?
  4. JAVA进阶开发之(String字符串的存储原理)
  5. 【BZOJ】1061: [Noi2008]志愿者招募
  6. 全新 AI 语音芯片、双麦 AIoT 模组,科大讯飞硬核技术助力智能家电创新
  7. 云存储是否能拯救数据泛滥
  8. 可以在python3下面用的pyh
  9. Julia: readcsv和 readdlm
  10. 极大似然估计法的理解
  11. 无线AP 传输、认证
  12. 如何进行网站代备案?
  13. 注册icloud邮箱
  14. 阿里云如何设置content-type,微软的在线预览无法使用问题
  15. 英国沦陷了!2014年英国婴儿名top10,穆罕默德意外夺魁
  16. Microsoft Visual C++ 14.0 is required.
  17. 课后作业十(定点计算)
  18. 上海职业学校计算机证书查询,证书查询
  19. csgo显示无法更新服务器,csgo更新无法连接服务器
  20. SAP历史库存MB5B的详解(转)

热门文章

  1. captivate 学习
  2. java 网络通讯用什么流_Java中打印流,网络通信协议,TCP通信的基础介绍
  3. 文字排版中的设计四原则(一)
  4. 如何提高英语的阅读理解【很经典的学习方法】
  5. NFS,RS宕机问题
  6. eclispe转 idea 快捷键设置(包括文件搜索运用)修改插入和改写模式
  7. tpc-ds基准测试案例-hive
  8. 关于注册公司流程(实操)。
  9. Go语言基础(codewars---6kyu和5kyu)
  10. 光圈倒闭背后的启示------什么样的直播平台可以存活?