【MySQL】SQL 优化

MySQL - SQL 优化

1. 在 MySQL 中,如何定位慢查询?

1.1 发现慢查询

现象:页面加载过慢、接口压力测试响应时间过长(超过 1s)

可能出现慢查询的场景:

  • 聚合查询
  • 多表查询
  • 表数据过大查询
  • 深度分页查询

1.2 通过现象定位到问题是出在 MySQL 的慢查询(查看慢日志法)

找到配置文件:

Windows:my.ini

在这里插入图片描述

Linux:/etc/my.cnf

在这里插入图片描述

添加或修改两个属性:

  1. slow_query_log=1(1 为 true,开启慢日志)
  2. long_query_time=2(单位为秒,超过 2 秒的将记录在慢日志)

选择性添加或修改,slow_query_log_file 属性,慢日志名

  • Linux 在/var/lib/mysql/localhost-slow.log
  • Windows 见配置文件默认值

重启 MySQL:

  • Windows

    • net stop MySQL
      
    • net start MySQL
      
  • Linux

    • sudo systemctl stop mysql
      
    • sudo systemctl start mysql
      

发现问题,找到对应的慢日志,定位到问题是出在 MySQL 的慢查询:

在这里插入图片描述

1.3 回答问题

  1. 介绍一下当时产生问题的场景(我们当时的一个接口测试的时候非常的慢,压力测试的结果大概 5 秒钟);
  2. 而我们在调试阶段,开启了 MySQL 的慢日志记录,我们设置的值为 2 秒,一旦 sql 执行超过 2 秒就会记录在慢日志中,我们发现问题后查询了 MySQL 的慢日志,最终定位到问题是出在 MySQL 的慢查询;

2. 那这个 SQL 语句执行很慢,是如何分析的呢?

可以采用 MySQL 自带的分析工具 explain

  • 通过 key 和 key_len 查询是否命中索引,也可以判断索引本身存在是否失效的情况;
  • 通过 type 字段查看 sql 是否有进一步的优化空间,是否村咋全索引扫描或者全盘扫描;
  • 通过 Extra 建议判断是否出现了回表的情况,如果出现了,可以尝试添加索引或者修改返回字段来修复;

在这里插入图片描述

  • possible_key 当前 sql 可能会使用到的索引

  • key 当前 sql 实际命中的索引

  • key_len 索引占用的大小

  • Extra 额外的优化建议

    在这里插入图片描述

  • type 这条 sql 的连接类型,性能由好到差:NULL、system、const、eq_ref、ref、range、index、all

    • NULL:没有使用到表
    • system:查询 MySQL 系统内置的表
    • const:根据主键索引查询
    • eq_ref:主键索引查询或者唯一索引查询
    • ref:索引查询
    • range:分为查询
    • index:索引树(全索引)扫描
    • all:全盘扫描

3. 了解过索引吗?(什么是索引)

3.1 索引是什么

索引(index)是帮助 MySQL 高效获取 数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构**(B+ 树)**,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

3.2 什么是 B+ 树

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.3 回答

了解过索引吗?

  • 索引(index)是帮助 MySQL 高效获取数据的有序的数据结构;
  • 提高数据检索的效率,降低数据库的 IO 成本,因为不需要全表扫描;
  • 通过索引列对数据进行排序,降低数据排序的成本,降低了 CPU 的消耗;

索引列:以表中哪个列来创建索引;

索引的底层数据结构了解过吗?

InnoDB是MySQL数据库管理系统中的一种事务性存储引擎。

MySQL 的 InnoDB 引擎采用的 B+ 树的数据结构来作为索引的存储结构;

  • MySQL 的索引的底层数据结构是 B+ 树;
  • 阶数更多,路径更短;磁盘读写代价低,非叶子节点只存储指针,叶子节点存储数据;
  • B+ 树便于扫库和区间的查询,叶子节点是一个双向链表;

4. 什么是聚簇索引,什么是非聚簇索引?

4.1 什么是聚集索引,什么是二级索引(非聚集索引)?

在这里插入图片描述

在这里插入图片描述

如果没有主键,则会使用隐藏字段:DB_ROW_ID,隐藏主键

4.2 什么是回表查询?

了解什么是聚集索引,什么是二级索引(非聚集索引)后,再进行理解:

在这里插入图片描述

如果没有主键,则会使用隐藏字段:DB_ROW_ID,隐藏主键进行回表查询(如果不给隐藏主键创建索引,那么回表查询是没有走索引的,效率低下)

4.3 回答

  • 聚簇索引(聚集索引):数据存放到索引中,B+ 树的叶子节点保存了整行数据,有且只有一个;
  • 非聚簇索引(二级索引,非聚集索引):数据不全部存放到索引中,B+ 树的叶子节点保存了索引列以及对应的主键,可以有多个;
  • 通过二级索引找到对应的主键值,再到聚集索引中查找整行数据,这个过程就是回表;(如果没有聚集索引,回表查询就不是通过索引查询了,而是全表查询,非常低性能)

5. 知道什么叫覆盖索引吗?

覆盖索引就是查询使用了索引,并且需要返回的列在该索引中已经全部覆盖到了;

在这里插入图片描述

  • 聚集索引一定是,二级索引不需要回表查询也是;

回答:

  • 聚集索引指的是查询使用了索引,返回的列,在索引中全部都能找到;
    • 使用 id 查询,直接走聚集索引查询,一次索引扫描,直接返回全部数据,性能高;
    • 如果所需列在索引中不存在,就会触发回表查询,所以尽量避免使用 select *

6. MySQL 超大分页怎么处理?

在数据量比较大的时候,如果进行 limit 分页查询,在查询的时候,越往后,分页查询效率越低。

6.1 超大分页场景

例如:

select * from user order by nickname limit 0, 10;
select * from user order by nickname limit 9000000, 10;

上面那个 0 毫秒不到,而下面那个甚至可以达到 10 秒以上!

因为,在执行的时候,需要加载 9000010 条记录(每条都是 raw),再选取 9000000 - 9000010 的记录,其他记录丢弃,查询排序的非常大。

而 nickname 在这里不是覆盖索引,所以加载 9000010 条记录时,性能很低。

  • order by 子句使用索引需要:
    1. order by 子句中的字段必须创建了索引,索引查询的字段覆盖需要查询的字段;
    2. order by 子句中的字段要符合最左前缀法则(对于复合索引);
  • 像这种非覆盖索引,回表的性能还不如全表查询呢,所以不走索引在这里是好事;

6.2 超大分页 SQL优化

但是我们知道这条 sql 中是覆盖索引:

select id from user ordery by nickname limit 9000000, 10;

那么我们再拿这 10 个 id 去表中查询即可。

因此 sql 可以优化成这样(覆盖索引 + 子查询):

select * from
	user u, 
	(select id from user order by nickname limit 9000000, 10) a
where u.id = a.id;

6.3 回答

  • 问题在于在数据量比较大时,limit 分页查询,需要对数据进行排序,效率低。

  • 可以用到索引(有序性)查询,而如果不是覆盖索引,那么可以用覆盖索引 + 子查询进行优化!

7. 索引创建的原则有哪些?

先陈述自己实际开发中怎么用索引的,用了什么索引,如主键索引、唯一索引、复合索引…

再说原则:

  1. 数据量较大,且查询比较频繁的表;(10w+ 就可以创建索引增加用户体验了)
  2. 常常作为查询条件、排序操作、分组操作的字段;
  3. 尽量使用联合索引(多列索引),减少单列索引,这样可以让查询更可能是覆盖索引;
  4. 要控制索引的数量,并不是越多越好,增删改都是需要维护的;
  5. 字段内容区分度高,尽量建立唯一索引,区分度越高性能越好;
  6. 字符串类型字段,内容较长,可以使用前缀索引;
  7. 如果索引列不能存储 NULL 值,在创建表的时候使用 NOT NULL 约束,这有利于让优化器选择哪个索引进行更有效的查询;

8. 什么情况下索引会失效?

8.1 复合索引

在这里插入图片描述

顺序见 Seq_in_index,即 name、status、address

8.2 违反最左前缀法则

SQL 的查询条件 / 排序 / 分组从索引的最左前列开始,才会走索引:

在这里插入图片描述

正向例子:

在这里插入图片描述

反向例子:

在这里插入图片描述

跳过某一列,则只有部分最左前缀索引生效:

在这里插入图片描述

8.3 范围查询右边的列,不能使用索引

在这里插入图片描述

下面那个,name 和 status 走索引,status 右边的字段 address 没用到索引。

8.4 不要再索引列上进行运算操作,索引会失效

在这里插入图片描述

8.5 字符串不加单引号,造成索引失效

在这里插入图片描述

复杂行为往往导致索引失效~

8.6 模糊查询有可能会导致索引失效

头部模糊匹配,索引失效。如果仅仅是尾部模糊匹配,索引不会失效。

在这里插入图片描述

8.7 回答

同理,先陈述自己的遭遇,如某个场景创建了索引,性能还是很慢,explain 去查看 sql 语句的执行计划,发现索引失效了。

对于复合索引:

  1. 违反最左前缀法则;
  2. 范围查询右边的列;
  3. 在索引列上进行运算操作;
  4. 字符串不加单引号,导致 MySQL 优化器进行类型转化;
  5. 头部模糊查询;

通常情况下,可以使用 explain 查看 sql 的执行计划来判断索引是否失效。

9. 谈一谈你对 SQL 优化的经验

从三个方面:

  1. 表的设计优化
  2. 索引优化(参考优化创建原则和索引失效)
  3. SQL 语句优化

9.1 表的设计优化(参考阿里开发手册《嵩山版》)

  1. 比如设置合适的数值(tinyint、int、bigint)要根据实际情况选择;
  2. 比如设置合适的字符串类型(char,varchar)char定长效率高,varchar可变长度,效率稍低;

9.2 SQL 语句的优化

  1. select 语句务必指明字段的名称(避免使用 select *);
  2. SQL 语句要避免造成索引失效的写法;
  3. 尽量用 union all 代替 union,union 会多一次过滤,效率低(union 会将重复的过滤掉,如果知道没有重复的就可以用 union all)

在这里插入图片描述

这个就不能用 union all,并不是存在绝对地去优化,而是看情况决定~

  1. 避免在 where 子句对字段进行表达式/函数操作;

  2. join 优化,能用 inner join 就不用 left join 或者 right join,如果必须使用,一定要以小表为驱动;

    • 小表:数据量较小的表,大表:数据量较大的表,

    • 这样的好处就是以小表连接大表,连接次数较小,on 子句查询的次数较小,并且由于是查询大表,所以如果是有索引,索引效果更明显!

    • 内连接会对两个表进行优化,优先把小表放外边,把大表放里面;

    • left join 或者 right join 则不会重新调整顺序;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/425658.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023 版王道单科书勘误汇总(3.30)

注:因2023版对题目编号做了优化“历年真题全部放最后、且按年份排序”,以方便大家根据需要保留某些年份的真题作为最后的模拟。所以造成了一些题目和解析的编号错误。 数据结构: P11 P20 P56 P278 P326 “2.”中第 3 行”题 5改成”9”,第6行”题 8”改成…

线性表——单链表的增删查改

本节复习链表的增删查改 首先, 链表不是连续的, 而是通过指针联系起来的。 如图: 这四个节点不是连续的内存空间, 但是彼此之间使用了一个指针来连接。 这就是链表。 现在我们来实现链表的增删查改。 目录 单链表的全部接口…

【EAI 027】Learning Interactive Real-World Simulators

Paper Card 论文标题:Learning Interactive Real-World Simulators 论文作者:Mengjiao Yang, Yilun Du, Kamyar Ghasemipour, Jonathan Tompson, Leslie Kaelbling, Dale Schuurmans, Pieter Abbeel 作者单位:UC Berkeley, Google DeepMind, …

探索设计模式的魅力:备忘录模式揭秘-实现时光回溯、一键还原、后悔药、历史的守护者和穿越时空隧道

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,并且坚持默默的做事。 备忘录模式揭秘-实现时光回溯、一键还原、后悔药和穿越时空隧道 文章目录 一、案例场景&…

19.1 SpringBoot入门

19.1 SpringBoot入门 1. SpringBoot1.1 简介1.2 核心特点1.3 SpringBoot演变1.4 SpringBoot版本1. SpringBoot 1.1 简介 1.2 核心特点

【系统分析师】-计算机组成结构

1、计算机结构 2、存储系统 Cache是访问最快 DRAM是存取最快 先来先服务 FCFS:按照磁道号访问顺序 最短寻道时间优先SSTF:查找下一个最少的磁道数。柱面相同找磁头、磁头相同找扇区 3、数据传输控制方式 4、总线 总线: 分 时 传 输 &#…

十四、计算机视觉-形态学梯度

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、梯度的概念二、梯度的应用三、梯度如何实现 一、梯度的概念 形态学梯度(Morphological Gradient)是数字图像处理中的一种基本操作&…

C++学习笔记:二叉搜索树

二叉搜索树 什么是二叉搜索树?搜索二叉树的操作查找插入删除 二叉搜索树的应用二叉搜索树的代码实现K模型:KV模型 二叉搜索树的性能怎么样? 什么是二叉搜索树? 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树…

数据处理——一维数组转列向量(分割时间序列为数据块时的问题)

记录在处理数据时被磕绊了一下的一个处理细节。 1.想要达到的要求 在某次滑动窗口取样时间序列数据时,我得到如下一个以一维数组为元素的列表: 对于如上输出列表中的每个一维数组,我希望将其转换为下图中的形式,简单说就是希望他…

3. springboot中集成部署vue3

1. vue3构建 构建命令 npm run build&#xff0c; 构建的结果在disc目录&#xff1a; 2. springboot集成 2.1 拷贝vue3构建结果到springboot resources/static目录 2.2 springboot pom依赖 添加thymeleaf依赖 <dependency><groupId>org.springframework.boot</…

文件操作命令touch、cat、more、cp、mv

touch 创建文件 1&#xff09;可以通过touch命令创建文件。 2&#xff09;语法&#xff1a; touch Linux路径 3&#xff09;touch命令无选项&#xff0c;参数必填&#xff0c;表示要创建的文件路径&#xff0c;相对、绝对、特殊路径符均可以使用。 注&#xff1a;以 d 开头的…

PlantUML - 时序图

时序图主要内容 下面是一个简单的时序图&#xff0c;我们可以很容易并且美观的表达我们的交互流程&#xff0c;只需要在箭头的两边指定一个名字&#xff0c;加上描述即可&#xff1a; startuml bkloanapply -> bkloanapprove : request bkloanapprove --> bkloanapply :…

LeetCode 刷题 [C++] 第215题.数组中的第K个最大元素

题目描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 题目分析 根据题意分析&…

C++入门和基础

目录 文章目录 前言 一、C关键字 二、命名空间 2.1 命名空间的定义 2.2 命名空间的使用 2.3 标准命名空间 三、C输入&输出 四、缺省参数 4.1 缺省参数的概念 4.2 缺省参数的分类 五、函数重载 5.1 函数重载的简介 5.2 函数重载的分类 六、引用 6.1 引用的…

WordPress介绍(开源内容管理系统(CMS),一个用于构建和管理网站的平台)

文章目录 Introduction to WordPress: Powering the Web with Simplicity and Flexibility&#xff08;WordPress简介&#xff1a;以简洁和灵活性驱动万维网&#xff09;Overview of WordPress&#xff08;WordPress概述&#xff09;Evolution of WordPress&#xff08;WordPre…

华为od机试C卷-最长表达式求值

1 题目描述 提取字符串中的最长合法简单数学表达式子串&#xff0c;字符串长度最长的&#xff0c;并计算表达式的值&#xff0c;如果没有返回0。简单数学表达式只能包含以下内容0-9 数字&#xff0c;符号* 说明: 1.所有数字&#xff0c;计算结果都不超过 long 2.如果有多个长…

基于yolov5的草莓成熟度检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的草莓成熟度检测系统&#xff0c;系统既能够实现图像检测&#xff0c;也可以进行视屏和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的草莓成熟度系统是在pytorch框架下实现的&#xff0c;这是一个完整的项目…

【XIAO ESP32S3 sense 通过 ESPHome 与 Home Assistant 连接】

XIAO ESP32S3 sense 通过 ESPHome 与 Home Assistant 连接 1. 什么是 ESPHome 和 Home Assistant&#xff1f;2. 软件准备3. 开始4. 将 Grove 模块与 ESPHome 和 Home Assistant 连接5. Grove 连接和数据传输6. Grove -智能空气质量传感器 &#xff08;SGP41&#xff09;7. OV2…

自学Python笔记总结(2——了解)

网络了解 网络调试助手 NetAssist.exe NetAssist.exe 使用方法请自行寻找 UDP协议 &#xff08;只能一来一回的的发消息&#xff0c;不可连续发送&#xff09; UDP 是User Datagram Protocol的简称&#xff0c; 中文名是用户数据报协议。在通信开始之前&#xff0c;不需要建…

【JavaEE】_Spring MVC 项目传参问题

目录 1. 传递单个参数 1.1 关于参数名的问题 2. 传递多个参数 2.1 关于参数顺序的问题 2.2 关于基本类型与包装类的问题 3. 使用对象传参 4. 后端参数重命名问题 4.1 关于RequestPara注解 1. 传递单个参数 现创建Spring MVC项目&#xff0c;.java文件内容如下&#xff…