于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. jmeter 压测的执行步骤步骤

    一.设置测试参数 如图 Number of Threads:总共起多少个线程. Ramp-UP Period(in seconds):多少秒启动完所有线程. loop Count:循环次数 Sched ...

  2. centos7 为文件夹添加写入权限

    [root@VM-16-15-centos ~]# sudo su[root@VM-16-15-centos ~]# cd /www/wwwroot/www.htqq.sale/php/images[ ...

  3. List,Set,Map存取元素各有什么特点 hashMap、hashTable的区别 Arraylist和linkedList的区别

    1.List,Set,Map存取元素各有什么特点? 1.存放 (1)List存放元素是有序,可重复 (2)Set存放元素无序,不可重复 (3)Map元素键值对形式存放,键无序不可重复,值可重复 2.取 ...

  4. 微信小程序—标题栏

    <template> <view :style="{paddingTop: statusBarHeight + 'px',background:bg}" clas ...

  5. 设计模式 - 单例模式 Singleton Pattern - C#

    单例模式 Singleton Pattern 1.单例模式设计模式属于创建型模式 2.是单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访 ...

  6. CMake制作我的第一个自己写的项目

    首先写好CMakeList.txt ,然后把目标文件(.off格式)和 源文件(.cpp) 放在同一目录下吗,对该目录进行Cmake 生成build文件,打开.sln 文件,运行ALL_BUILD , ...

  7. WPF dxe:ComboBoxEdit 选择项后并可编辑值

    有个需要,在ComboBoxEdit中选择多个值,并且要求可以直接在后面添加新的值. 开始的时候绑定列表,设置DisplayMember,不能修改. 然后绑定List<string>,不设 ...

  8. awk sub string

    cat TFY1C.txt|awk '{print $0"\t"substr($4,1,4)}'> TFY1CRID.tx 1--从那位开始 4--多长

  9. vs2019远程调试win7系统的程序

    vs2019远程调试   一.安装vs2019远程调试工具 首先让调试的电脑(也就是不安装vs2019的电脑),安装vs2019远程调试工具:VS_RemoteTools.exe. 网址:进行下载.h ...

  10. 12-如何使用Genarator逆向工程

    使用逆向工程,帮我们更快的建立pojo类.mapper接口及xml映射文件等,无需手写,替代了一部分的mybatis功能. 一.导入MyGenarator逆向工程项目 二.修改xml配置文件 三.执行 ...