最近做一个CRM系统,发现了慢查询日志里记载了许多的慢sql,于是就对其进行了sql优化。在优化的过程中,自己也归纳整理了一些sql优化的方案。今天就来和大家聊聊。

**1、慢查询的分析**
常见的分析慢查询sql的方法大概有三种:explain、show profile、trace 分析 sql优化器。本文主要介绍explain的方法去分析慢sql,其余两种方法有兴趣的同学可以去了解下。

**2、explain各参数解释**
(1)explain语法:explain+“需分析的sql”;
例:我想分析“select * from table1 where b=500;”这条sql的执行效率,那么直接在sql命令行下执行“expalin select * from table1 where b=500;”就可以查看了;执行结果如下:

根据上图,可以看到有许多个字段,那这些字段分别有什么意义呢?见下图(红框标出的为重点关注字段):

其中各个字段又可能有多个不同的值,重点关注字段select_type、type、Extra的可能值如下图所示:


其中,上图中的“type”的值的查询性能从上到下依次是最好到最差。

**3、常用sql优化方法**

(1)使用索引
大家对MySQL的索引应该不会感到陌生吧,数据量大的时候,最常见的加快查询效率的方法那肯定是加索引了,要知道MySQL的B+索引树可是能在2~4层树就能从上亿的数据中提取出相关数据的,不加索引的话得进行上亿次磁盘io查找(关于B+树的具体原理,大家可以参考下这篇文章,写得很不错,http://www.liuzk.com/410.html。索引虽好用,但是存在很多不走索引的情况。下面列举常见几种不走索引的情况,以及如何让它走索引:
①对查询条件使用函数
如:select * from table1 where date(c) ='2020-08-20';
应改为:select * from table1 where c>='2020-08-20 00:00:00' and c<='2020-08-20 23:59:59';
②隐式转换:如把varchar类型当成int型去写
例:select * from table1 where a=1000; (其中,a字段在数据库中是varchar类型)
应改为:select * from table1 where a='1000';
③模糊查询
如:select * from table1 where a like '%1111%';
应改为:select * from table1 where a like '1111%'; 但要看具体业务,可能不对
注意:select * from table1 where a like '%1111'; 这种也是不走索引的
可以这么理解:like 匹配是%在前面的都不走索引
④范围查询
如:select * from table1 where b>=1 and b <=2000; (这条数据查询范围过大,是全表扫描,优化器选择不走索引)
应改为:select * from table1 where b>=1 and b <=1000;
select * from table1 where b>=1001 and b <=2000;
⑤计算操作 (但一般在代码层面做操作,很少会在数据库做操作)
如:select * from table1 where b-1 =1000;
应改为:select * from table1 where b =1000 + 1;
⑥OR 操作
如果条件中有OR,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引。所以除非每个列都建立了索引,否则不建议使用OR,在多列OR中,可以考虑用UNION 替换
如:select * from table1 where create_time = '2020-08-20 11:49:30' OR b > 854;
应改为:select * from table1 where create_time = '2020-08-20 11:49:30' UNION select * from table1 where b > 854;

(2)分页优化
如:select * from table1 order by a limit 99000,10; (其中,a字段有索引)
但结果不走索引,原因是扫描整个索引并查找到没索引的行的成本比扫描全表的成本更高,所以优化器放弃使用索引。(关键是让排序时返回的字段尽可能少)
应改为:select * from table1 f inner join (select id from table1 order by a limit 99000,10)g on f.id = g.id;
或者 select * from table1 where id >= (select id from table1 order by a limit 99000,1) limit 10;

(3)连接查询优化
在项目中,表连接查询是比较常见的,尤其是一些统计模块。表连接有两种算法,一种叫Nested-Loop Join 算法(简称NLJ),另一种是Block Nested-Loop Join 算法(简称BNL)(关联字段不存在索引时会使用到)。感兴趣的小伙伴可以深入去了解下相关原理哦。我们进行关联查询优化的方法是:尽量让 BNL变成 NLJ ,就是说在关联字段上加上索引。

(4)order by和group by优化
①首先我们要知道MySQL中有两种排序方式,一种是通过有序索引直接返回有序数据(Extra字段:Using index);另一种是通过 Filesort 进行的排序,不走索引(Extra字段:Using filesort);毫无疑问,肯定是有序索引排序更快。
常见order by优化方法:
①在排序字段上添加索引
如:select c,id from table1 order by c; (c有索引)
②多个字段排序,可以在多个排序字段上添加联合索引来优化排序语句
如:select id,a,b from table1 order by a,b; (a,b是联合索引)
注意:select id,a,b from table1 order by b,a; (a,b是联合索引)此时不走索引,最左匹配前缀原则了解下
③对于先等值查询再排序的语句,可以通过在条件字段和排序字段添加联合索引来优化
如:select id,a,b from table1 where a=1000 order by b; (a,b是联合索引)
如果a,b不是联合索引的话,即时有a索引,b索引,排序也不会走索引
④去掉不必要的返回字段
如:select * from table1 order by a,b; /* 根据a和b字段排序查出所有字段的值 */
应改为:select id,a,b from table1 order by a,b; /* 根据a和b字段排序查出id,a,b字段的值 */
不走索引原因:扫描整个索引并查找到没索引的行的成本比扫描全表的成本更高,
所以优化器放弃使用索引。

默认情况,会对 group by 字段排序,因此group by优化方式与 order by 基本一致。

本篇文章就写到这,你们工作中还有什么好的优化sql的方法吗?欢迎在评论区分享!

MySQL慢查询及优化的更多相关文章

  1. 开启Mysql慢查询来优化mysql

    开启Mysql慢查询来优化mysql 优化sql语句是优化数据库的一个很重要的方面,那么怎么发现那些耗时耗资源的sql语句呢,开启Mysql慢查询! 1.查看是否开启慢查询,默认情况下是关闭的.你的m ...

  2. mysql数据库优化课程---16、mysql慢查询和优化表空间

    mysql数据库优化课程---16.mysql慢查询和优化表空间 一.总结 一句话总结: a.慢查询的话找到存储慢查询的那个日志文件 b.优化表空间的话可以用optimize table sales; ...

  3. MySQL子查询的优化

    本文基于MySQL5.7.19测试 创建四张表,pt1.pt2表加上主键 mysql> create table t1 (a1 int, b1 int); mysql> create ta ...

  4. MySql学习—— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  5. MySQL之查询性能优化(四)

    优化特定类型的查询 COUNT()的作用 COUNT()是一个特殊函数,有两个非常不同的作用:它可以统计某个列值的数量,也可以统计行数.在统计列值时要求列值是非空的(不统计NULL). 如果在COUN ...

  6. MySQL之查询性能优化(三)

    MySQL查询优化器的局限性 MySQL的万能“嵌套循环”并不是对每种查询都是最优的.不过还好,MySQL查询优化只对少部分查询不适用,而且我们往往可以通过改写查询让MySQL高效地完成工作. 关联子 ...

  7. MySQL之查询性能优化(二)

    查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的.MySQL执行一个查询的过程,根据图1-1,我们可以看到当向MySQL发送一个请求时, ...

  8. MySQL之查询性能优化(一)

    为什么查询速度会慢 通常来说,查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段, ...

  9. 使用聚集索引和非聚集索引对MySQL分页查询的优化

    内容摘录来源:MSSQL123 ,lujun9972.github.io/blog/2018/03/13/如何编写bash-completion-script/ 一.先公布下结论: 1.如果分页排序字 ...

  10. mysql 分页查询及优化

    1.分页查询 select * from table limit startNum,pageSize 或者 select * from table limit pageSize offset star ...

随机推荐

  1. MyBatis-Plus 代码生成(新)

    MyBatis-Plus 的代码生成功能十分人性化,即支持通过简单的配置实现,也可以通过自定义模板实现. 这里列出项目中的常用配置供参考,其他配置可以参考官网:https://baomidou.com ...

  2. Servlet和springMVC

    什么是Servlet? Servlet是使用Java语言编写的运行在服务器端的程序.狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一 ...

  3. 在ECS上安装部署openGauss数据库指导手册

    在 ECS 上安装部署 openGauss 数据库指导手册 文档下载:在 ECS 上安装部署 openGauss 数据库指导手册.docx 前 言 简介 openGauss 是关系型数据库,采用客户端 ...

  4. 一、Unity调用Xcode封装方法(工程引用文件)

    1.Xcode新建Static Library 工程 (我起的名字是UnityExtend 可以在接下来的图中看到) 2.打包unity ios工程 unity打包ios 打出Xcode工程 3.打开 ...

  5. k8s 深入篇———— k8s 的pod[五]

    前言 简单整理一下pod的相关知识. 正文 为什么我们需要pod. 前面我们知道了k8s一个最重要的作用是解决容器的编排功能,那么为什么有一个pod的东西. 这就是实际中遇到的问题. 那就是容器和容器 ...

  6. 力扣48(java)-旋转图像(中等)

    题目: 给定一个 n × n 的二维矩阵 matrix 表示一个图像.请你将图像顺时针旋转 90 度. 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要 使用另一个矩阵来旋转图像 ...

  7. 阿里云2020上云采购季,你最pick哪个产品组合?

    阿里云2020上云采购季如火如荼进行中,活动还剩最后10天啦,你的云产品都买好了吗? 还没买的,还没逛的,请戳:https://www.aliyun.com/sale-season/2020/proc ...

  8. 从 Flink Forward Asia 2021,看Flink未来开启新篇章

    ​简介:本文将对FFA Keynote议题作一些简单的归纳总结,感兴趣的小伙伴们可以在FFA官网[2]找到相关主题视频观看直播回放. ​ 作者 | 梅源(Yuan Mei) 来源 | 阿里技术公众号 ...

  9. 一文详解 | 开放搜索兼容Elasticsearch做召回引擎

    ​简介:开放搜索发布开源兼容版,支持阿里云Elasticsearch做搜索召回引擎,本文详细介绍阿里云ES用户如何通过接入开放搜索兼容版丰富行业分词库,提升查询语义理解能力,无需开发.算法投入,即可获 ...

  10. 网不好怎么办?TLS握手带宽直降80%,BabaSSL是怎么做到的?| 龙蜥技术

    ​简介:为了保障数据的安全性,客户端会先和服务器进行 TLS 握手,有什么办法可以减少 TLS 握手的带宽消耗呢? 编者按:BabaSSL 是一款开源的密码库产品,在 GitHub 和龙蜥社区开源,并 ...