于2023.3.17日重写,之前写的还是太八股文太烂了一点逻辑都没有,这次重新写了之后,感觉数据库优化还是很有必要的,之前觉得不必要是我年轻了。

一、如何定位慢SQL语句

1、通过慢查询日志查询已经执行完的SQL语句

默认慢查询日志不会开启,需要手动设置,命令为

mysql> set global slow_query_log = on;

也可以根据业务设置时间阈值以及查看慢查询日志的存储位置和文件名,自行百度

然后可以通过查询日志的方式,定位到慢SQL语句,比如使用tail命令

2、通过processlist查看正在执行的慢SQL语句

这个没什么好说的,在mysql>终端中,使用show processlist指令或者show full processlist

二、如何分析慢SQL语句

使用老朋友explain关键字explain+分析的sql语句即可,一般来说,我们需要重点关注selectType,type、rows、extra、key。

关键字 含义 常见
selectType 查询类型 simple,primary,union
type 表连接类型 ref,index,range,all
rows 预计需要扫描的行数 是估值
key 实际使用的索引
extra 附加信息 Using index,Using temporary,using filesort

三、分析慢SQL语句的原因

1、大部分慢SQL语句优化都跟索引有关系,查看是不是索引设置不合理,索引失效等问题

2、一部分是sql语句本身有关系,比如深分页,in元素过多,对非索引字段进行排序等,可以考虑优化sql语句

3、小部分与sql语句无关,比如大数据表的查询确实会比较慢

四、常见的SQL优化

  1. 优化Order By

首先,我们先知道Order by是如何实现的,order by的功能我们都知道,就是使用By后面的一个或者多个字段进行排序,我们假设现在有这么一个需求,对周杰伦的歌曲按照播放量进行排序,查出歌手,歌曲编码,歌曲曲风,播放量等播放,很容易写出来

select singer,song_code,song_types,conuts FROM `song` where singer='周杰伦' order by counts

我们假设对singer字段加了一个索引,这样避免全表扫描,那么这条sql语句应该是这样执行的。

a. 初始化sort_buffer,放入所有select字段(可以理解是在sort_buffer这块内存中初始了select所需字段的一张表)

b. 从索引singer 找出第一条满足singer是周杰伦的行记录的主键(不懂的同学可以看下辅助索引的概念,简单来说非主键索引的B+树叶子节点是主键索引),根据主键进行回表 取出select所需的字段放入sort_buffer中

c. 重复b操作,直到所有满足条件的记录放入sort_buffer中了,然后sort_buffer内部根据字段counts进行快速排序,返回结果

以上这种实现方式,叫做全字段排序,观察这种实现方式,它的特点就是要把select的所有字段放入sort_buffer中,尽管只需要一个字段进行排序,它的问题也很明显,我用黄色高亮出来了,所有字段都放入sort_buffer中,如果select了好多个字段或者sort_buffer设置的太小(自行百度,没必要记住这种命令),那内存就顶不住了,得靠磁盘中的内部文件帮忙,此时外部文件使用归并排序。

解决这个问题的就是order by的第二种实现方式 rowid排序,这种实现方式也很好理解,就是sort_buffer中只放两种类型的字段,一种就是需要排序的字段,另一种就是主键(一般就是id作为主键),那么sql语句执行方式就不太一样了。

a. 初始化sort_buffer,放入需要排序的字段和id字段

b.根据辅助索引singer找出第一条满足singer是周杰伦的行记录的主键,根据主键进行回表,取出主键id和counts字段放入sort_buffer中

c. 重复b操作,直到所有满足条件的记录放入sort_buffer中了,然后sort_buffer内部根据字段counts进行快速排序

d. 根据排序后的主键id进行回表,取出select需要的字段返回

这就是rowid排序的实现方式,也很明显,这种方式需要两次回表操作,所以并不是一定会比所有字段排序方式好

那如何解决呢?答案页很简单,说到底还是我们的索引设置的不够合理。

对于这种情况优化,我们可以采用设置联合索引的方式进行优化,如果联合索引设置的好,那天然就是有序的了,就没必要进行排序了,同时也可以解决回表问题(索引覆盖),比如针对这个需求,我们可以创建这样的一个联合索引

alter table `song` add index singer_counts_song_code_song_types(singer,counts,song_code,song_types);

注意顺序,singer,counts字段一定要在前两个,如果理解不了的话,要去学习一下联合索引的结构原理。

当然这样做也有局限,比如确实不应该添加索引或者where条件不只有周杰伦也可能是周杰伦和周深的歌曲播放量排名。

  1. llimit深分页优化

limit深分页问题也是大数据领域常见的问题了,很多小白包括我之前并不了解limit的用法,我先简单介绍下limit的用法。 limit offset,n 先是偏移量然后才是真正读取的n条数据,其含义是扫描offset+n条数据然后抛弃前offset条数据,留下最后n条数据。

为什么说深分页不好呢,答案也很简单如果offset很大,那么很大可能会有很多无效的回表,那是因为较多场景其实是利用了辅助索引(例如上面的那个需求,主键就是无意义的id,真正有利用信息的是辅助索引),这么多无效的回表是难以接受的,常见的优化手段有:

我们可以利用子查询优化深分页,这样就避免了回表操作,例如《阿里巴巴java性能调优实战》中的例子

## 需求是返回10000条之后的20条记录
##### 未优化:
select * from `order` order by order_no limit 10000,20
##### 子查询优化:
select * from `order` where id >(select id from `order` order by order_no limit 10000,1) limit 20

id是主键,因此也没有了回表问题

或者如果我们提前知道搜索范围是10001到10020,那么我们就可以直接使用between and范围查询来避免limit深分页问题,当然前提是order by的字段是连续的,而且要知道准确需求范围(很多都是从上次查询的位子开始后n行,这就不行了)

  1. in内元素过多

in本身操作性能就不高,加上元素太多会造成很大的性能浪费,目前我并没有查找到常用的解决方案,我这里给出我常用的方法,如果in里面的元素还是可以枚举的,那么可以尝试union all各个条件select出的结果,如果是不能枚举的,阿里巴巴有个类Mysql的PolarDB mysql有对大量in进行优化 [阿里巴巴文章](PolarDB for MySQL优化器查询变换系列 - IN-List变换 - 陈江的文章 - 知乎 https://zhuanlan.zhihu.com/p/591601424)

五、参考文章

  1. Order By优化
  2. Mysql深分页
  3. Mysql索引

SQL优化---慢SQL优化的更多相关文章

  1. Oracle数据库该如何着手优化一个SQL

    这是个终极问题,因为优化本身的复杂性实在是难以总结的,很多时候优化的方法并不是用到了什么高深莫测的技术,而只是一个思想意识层面的差异,而这些都很可能连带导致性能表现上的巨大差异. 所以有时候我们应该先 ...

  2. SQL Server数据库性能优化技巧

    查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引: 2.I/O吞吐量小,形成了瓶颈效应: 3.内存不足: 4.网络速度慢: 5.查询出的数据量过大: 6.锁或者死锁: 7.返回了不必 ...

  3. 【转】使用SQL Tuning Advisor STA优化SQL

    SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它的特点是简单.智能,DBA值需要调用函数就可以给出一个性能很差的语句的优化结果.下面介绍一 ...

  4. 如何用 SQL Tuning Advisor (STA) 优化SQL语句

    在Oracle10g之前,优化SQL是个比较费力的技术活,不停的分析执行计划,加hint,分析统计信息等等.在10g中,Oracle推出了自己的SQL优化辅助工具: SQL优化器(SQL Tuning ...

  5. 【转】MySQL批量SQL插入各种性能优化

    原文:http://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=403182899&idx=1&sn=74edf28b0bd29 ...

  6. SQL Server数据库性能优化之SQL语句篇【转】

    SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...

  7. SQL SERVER 查询性能优化——分析事务与锁(五)

    SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...

  8. SQL Server 查询性能优化 相关文章

    来自: SQL Server 查询性能优化——堆表.碎片与索引(一) SQL Server 查询性能优化——堆表.碎片与索引(二) SQL Server 查询性能优化——覆盖索引(一) SQL Ser ...

  9. Oracle性能优化之SQL语句

    1.SQL语句执行过程 1.1 SQL语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. ...

  10. 最有效地优化 Microsoft SQL Server 的性能

      为了最有效地优化 Microsoft SQL Server 的性能,您必须明确当情况不断变化时,性能将在哪些方面得到最大程度的改进,并集中分析这些方面.否则,在这些问题上您可能花费大量的时间和精力 ...

随机推荐

  1. 在Unity3D中开发的坦克履带模拟器Tank Track Simulator

    为了在Unity游戏中比较真实地模拟坦克履带的运动,本人便开发了这款Tank Track Simulator插件 特点 比较真实地模拟了坦克履带的运动. 本插件中包含了一辆M1A2坦克模型,已经将这个 ...

  2. MySQL备份管理

    MySQL备份管理 目录 MySQL备份管理 一.MySQL备份管理 1.1.1 MySQL备份管理介绍 1.1.2 基于mysqldump的备份恢复 1.1.3 基于xtrabackup软件的物理备 ...

  3. vcsa7 页面出现“no healthy upstream”处理过程

    一.昨天服务器出现"no healthy upstream"错误无法登录,搜索网络给出一下的思路: 对于"no healthy upstream"的错误提示,可 ...

  4. maven的下载与安装 win10系统

    1.安装maven的前提是jdk环境要配置好 不然下载jar包的时候会出错 2. Maven软件安装包下载 (推荐官网下载) 官网地址https://maven.apache.org/ 然后 3.下载 ...

  5. sar与ksar使用显示监控数据

    一.Ksar: 1)下载ksar地址:https://github.com/vlsi/ksar/releases/tag/v5.2.4-snapshot.10-gf068072 2)启动:java - ...

  6. .netCore Nuget包引用记录

    1.画图  System.Drawing.Common 2.

  7. 字节过滤流 缓冲流-->BufferedInputStream用法

    1创建字节输入节点流FileInputStream fis = new FileInputStream("文件读取的路径");2创建字节输入过滤流,包装一个字节输入节点流Buffe ...

  8. Python自学day03

    1.数据类型 int       1,2,3用于计算 bool    True,False用于判断 str       存储少量数据,用于操作 list       存储大量数据  [1,2,3,'a ...

  9. 用C#语言实现记事本

    一.实验内容: 二.记事本所需功能: (1)记事本程序具有文件的新建.打开.保存功能: (2)文字的复制.粘贴.删除功能:字体类型.格式的设置功能: (3)查看日期时间等功能,并且用户可三根据需要显示 ...

  10. webpack逆向之报错Cannot read properties of undefined (reading 'call')

    经典报错 记录一下: 1: 缺少模块    补上 2.主模块无法调用子模块   有可能网站用的数组形式的模块包,你用的是对象,调用方法就要改变. 改写过程中 用的是对象方式: 那么3号包调用的4号包 ...