【MySQL】SQL 优化

news2024/9/29 21:18:50

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 则不会重新调整顺序;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Flink精讲】Flink反压调优

Flink 网络流控及反压的介绍: Apache Flink学习网 反压的理解 简单来说, Flink 拓扑中每个节点(Task)间的数据都以阻塞队列的方式传输,下游来不及消费导致队列被占满后,上游的生产也会被阻塞,…

Jessibuca 插件播放直播流视频

jessibuca官网&#xff1a;http://jessibuca.monibuca.com/player.html git地址&#xff1a;https://gitee.com/huangz2350_admin/jessibuca#https://gitee.com/link?targethttp%3A%2F%2Fjessibuca.monibuca.com%2F 项目需要的文件 1.播放组件 <template ><div i…

Qt项目:网络1

文章目录 项目&#xff1a;网路项目1&#xff1a;主机信息查询1.1 QHostInfo类和QNetworkInterface类1.2 主机信息查询项目实现 项目2&#xff1a;基于HTTP的网络应用程序2.1 项目中用到的函数详解2.2 主要源码 项目&#xff1a;网路 项目1&#xff1a;主机信息查询 使用QHostI…

浅析ARMv8体系结构:原子操作

文章目录 概述LL/SC机制独占内存访问指令多字节独占内存访问指令 独占监视器经典自旋锁实现 LSE机制原子内存操作指令CAS指令交换指令 相关参考 概述 在编程中&#xff0c;当多个处理器或线程访问共享数据&#xff0c;并且至少有一个正在写入时&#xff0c;操作必须是原子的&a…

JAVA集合进阶(Set、Map集合)

一、Set系列集合 1.1 认识Set集合的特点 Set集合是属于Collection体系下的另一个分支&#xff0c;它的特点如下图所示 下面我们用代码简单演示一下&#xff0c;每一种Set集合的特点。 //Set<Integer> set new HashSet<>(); //无序、无索引、不重复 //Set<…

【kubernetes】关于k8s集群中kubectl的陈述式资源管理

目录 一、k8s集群资源管理方式分类&#xff1a; &#xff08;1&#xff09;陈述式资源管理方式&#xff1a;增删查比较方便&#xff0c;但是改非常不方便 &#xff08;2&#xff09;声明式资源管理方式&#xff1a;yaml文件管理 二、陈述式资源管理方法&#xff1a; 三、ku…

计算机设计大赛 深度学习大数据物流平台 python

文章目录 0 前言1 课题背景2 物流大数据平台的架构与设计3 智能车货匹配推荐算法的实现**1\. 问题陈述****2\. 算法模型**3\. 模型构建总览 **4 司机标签体系的搭建及算法****1\. 冷启动**2\. LSTM多标签模型算法 5 货运价格预测6 总结7 部分核心代码8 最后 0 前言 &#x1f5…

Nodejs 第四十二章(jwt)

什么是jwt? JWT&#xff08;JSON Web Token&#xff09;是一种开放的标准&#xff08;RFC 7519&#xff09;&#xff0c;用于在网络应用间传递信息的一种方式。它是一种基于JSON的安全令牌&#xff0c;用于在客户端和服务器之间传输信息。 https://jwt.io/ JWT由三部分组成&…

FL Studio All Plugins Edition2024中文完整版Win/Mac

FL Studio All Plugins Edition&#xff0c;常被誉为数字音频工作站&#xff08;DAW&#xff09;的佼佼者&#xff0c;是音乐制作人和声音工程师钟爱的工具。它集音频录制、编辑、混音以及MIDI制作为一体&#xff0c;为用户提供了从创作到最终作品输出的完整工作流程。这个版本…

下载huggingface数据集到本地并读取.arrow文件遇到的问题

文章目录 1. 524MB中文维基百科语料&#xff08;需要下载的数据集&#xff09;2. 下载 hugging face 网站上的数据集3. 读取 .arrow 文件报错代码4. 纠正后代码 1. 524MB中文维基百科语料&#xff08;需要下载的数据集&#xff09; 2. 下载 hugging face 网站上的数据集 要将H…

CrossOver24破解版下载安装与激活

在 Mac 上运行Windows 软件&#xff0c;CrossOver Mac 可以轻松地从 Dock 本地启动 Windows 应用程序&#xff0c;并将 Mac 操作系统功能&#xff08;如跨平台复制和粘贴以及共享文件系统&#xff09;集成到您的 Windows 程序中。 CrossOver 产品特性 无需重启 CrossOver 可以…

python Matplotlib Tkinter(pack)-->最大化去掉,仅剩关闭按钮

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pillow 10.1.0 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox import …

C/C++基础语法

C/C基础语法 文章目录 C/C基础语法头文件经典问题秒数转换闰年斐波那契数列打印n阶菱形曼哈顿距离菱形图案的定义大数计算 输入输出格式化输入输出getline()函数解决cin只读入一个单词的问题 运算符赋值运算符 Switch循环处理未知数量输入的几种常见方法for-each 字符串String字…

Dell Vestro 7500 Realtek ALC236 耳机插入无效无声音 解决

查了很多&#xff0c;试了很多。 最终还下是重启设备来得最简单有效。 无效方式&#xff1a; 安装最新驱动&#xff1a;没有236这个芯片&#xff0c;找不到官方驱动使用旧驱动&#xff1a;问题依旧使用驱动程序中的禁用设备&#xff0c;启用后还是没有&#xff08;以前好像也…

Kubernetes部署及运用

Kubernetes 1. Kubernetes介绍 1.1 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xf…

2024程序员容器化上云之旅-第4集-Ubuntu-WSL2-Windows11版:夺取宝剑

故事梗概 Java程序员马意浓在互联网公司维护老旧电商后台系统。 渴望学习新技术的他在工作中无缘Docker和K8s。 他开始自学Vue3并使用SpringBoot3完成了一个前后端分离的Web应用系统&#xff0c;并打算将其用Docker容器化后用K8s上云。 6 夺取宝剑 &#x1f525;阅读Nigel…

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(下)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

二叉树进阶oj练习

目录 1. 根据二叉树创建字符串 1&#xff09;思路 2&#xff09;代码实现 2. 二叉树前序非递归遍历实现 1&#xff09;思路&#xff1a; 2&#xff09;代码实现 3. 二叉树中序非递归遍历实现 1&#xff09;思路&#xff1a; 2&#xff09;代码实现&#xff1a; 4. 二…

Programming Abstractions in C阅读笔记:p303-p305

《Programming Abstractions in C》学习第74天&#xff0c;p303-p305总结&#xff0c;总计3页。 一、技术总结 1.时间复杂度分类(complexity classes) ClassNotationExampleconstantO(1)Returning the first element in an arraylogarithmicO(logN)Binary search in a sorte…

三菱plc控制双控电磁阀(从接线到程序)

目录 硬件设备 电磁阀的类型&#xff08;下图为例&#xff09; 三菱plc的类型&#xff08;西门子控正COOM接接正极&#xff0c;三菱控负COM接负极&#xff09; 气缸图 三菱plc与双控电磁阀接线 输出接线图&#xff08;COOM输出的公共端&#xff0c;三菱控负COM接负极&#x…