【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 * fromuser 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.mzph.cn/news/716662.shtml

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

相关文章

错误笔记:Anaconda 错误(闪退、无法安装等) + Pycharm 错误(无法启动)+ python 报错

Anaconda 错误 1、导航器启动中发生-- 闪退 方法一: Windows下: 1)使用管理员运行:conda prompt 2)执行命令 conda update anaconda-navigator 方法二: 重置Anaconda配置:anaconda-navigator…

C语言第三十四弹---动态内存管理(下)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 动态内存管理 1、动态内存经典笔试题分析 1.1、题目1 1.2、题目2 1.3、题目3 1.4、题目4 2、柔性数组 2.1、柔性数组的特点 2.2、柔性数组的使用 2.3、…

【c++】计算树的深度和节点数

在C语言中,计算给定树的层数(深度)和节点总数通常需要使用递归方法。首先,我们需要定义树的节点结构。这里假设我们处理的是一棵二叉树,每个节点有两个子节点(左子节点和右子节点)。 下面是一个…

5.STL源码解析-算法、仿函数、适配器

算法 STL算法总览 仿函数与适配器 C标准模板库(STL)是C程序员的得力工具,提供了许多强大而高效的数据结构和算法。在STL中,仿函数(Functor)和适配器(Adapter)是两个重要的概念…

C语言文件操作(fputs() 和 puts() 有两个小区别)

fputs() 和 puts() 有两个小区别: 1.puts() 只能向标准输出流输出,而 fputs() 可以向任何流输出。 2.使用 puts() 时,系统会在自动在其后添加换行符;而使用 fputs() 时,系统不会自动添加换行符。 那么这是不是意味着使…

【C++精简版回顾】17.io流,流中提供的函数

1.流含义 2.流类 3.流对象 4.流对象的函数 举例&#xff1a; 要求&#xff1a;数据结构中经常需要对齐输出数据&#xff0c;应该怎么做&#xff1f; 1.头文件 #include<iomanip> 2.创建表格头 cout << setiosflags(ios::left) << setw(8) << "姓名…

BUGKU 网站被黑

打开环境&#xff0c;什么都没发现&#xff0c;使用蚁剑扫描一下&#xff0c;发现shell.php&#xff0c;打开 使用BP抓包&#xff0c;进行爆破 得到密码&#xff1a;hack 进去得到flag

GEE高阶应用python wxee——如何利用来自 GOES-16 和 MODIS 的数据来可视化火灾随时间的进展分析

火灾进展 wxee 是专为处理气象数据而设计的,但它对遥感数据也很有用。在本示例中,我们将了解 wxee 如何利用来自 GOES-16 和 MODIS 的数据来可视化火灾随时间的进展情况。 安装和设定 #!pip install wxeeimport ee import wxeeee.Authenticate() wxee.Initialize(project=x…

每日一类:QLabel深入解析

QLabel是Qt中用于显示文本或图像的控件&#xff0c;属于Qt Widgets模块。它是展示静态内容的理想选择&#xff0c;支持富文本格式&#xff0c;使得文本可以包含不同的字体、颜色和链接。QLabel也可以用来显示图像&#xff0c;包括动态图像。此外&#xff0c;它还支持文本和图像…

【Java面试题】SpringBoot与Spring的区别

主要区别体现几个方面&#xff1a; 1.操作简便性 SpringBoot提供极其快速和简化的操作&#xff0c;使得Spring开发者能更快速上手。它通过提供spring的运行配置&#xff0c;以及为通用spring项目提供许多非功能性特性&#xff0c;进一步简化了开发过程。 2.框架扩展性 Spri…

算法学习——差分

在了解差分之前&#xff0c;我们首先需要知道前缀和的概念。 前缀和简单介绍&#xff1a; 对于一个数组A&#xff0c;要求出A[0]~A[i]的和&#xff0c;我们通常的做法是遍历一边&#xff0c;加起来。但是要求m组这样的和&#xff0c;我们就要花费O(mn)的时间复杂度。显然不合…

【考研数学】汤家凤1800题什么水平?

我觉得汤家凤基础武忠祥强化这个组合非常的不错 汤家凤老师的讲课风格 汤家凤老师的基础课程是大家公认的讲的详细&#xff0c;并且非常照顾基础不好的学生&#xff0c;会把基础知识点掰开揉碎的讲给大家听&#xff0c;在上课过程中&#xff0c;还会把知识点写在A4纸上&#…

试了下新型的360AI搜索

360AI搜索 试了下&#xff0c;感觉还是挺不错的。 比如问这个问题&#xff1a; ERROR 1698 (28000): Access denied for user rootlocalhost 它的回答&#xff1a; 对于ERROR 1698 (28000): Access denied for user rootlocalhost的问题&#xff0c;这通常是由于MySQL密码为…

【Javascript】设计模式之单例模式

文章目录 1、实现单例模式2、透明的单例模式3、用代理实现单例模式4、JavaScript 中的单例模式5、惰性单例6、通用的惰性单例7、小结 定义&#xff1a; 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点 单例模式是一种常用的模式&#xff0c;有一些对象我们往…

JavaScript 学习总结(16)—— 实用小函数总结

1.匹配正整数 // 匹配正整数 let isPositiveNum = val => {return /^[1-9]d*$/.test(val); }; console.log(isPositiveNum(9)) //true console.log(isPositiveNum(2.2)) //false 2.匹配负整数 // 匹配负整数let isNegativeNum = val => {return /^-[1-9]d*$/.test(val…

R750 install AMD MI210GPU

一、 查看服务器GPU卡信息 可以首先在服务器上check 当前GPU的详细信息是否匹配 二、安装 Ubuntu22.04操作系统 服务器CHECK 安装的AMD GPU 是否被系统识别 #lspci | grep AMD 查看GPU信息 可以看到已经识别成功 三、安装AMD GPU驱动 https://rocm.docs.amd.com/projec…

linux 根目录下结构

/ 虚拟目录的根的目录&#xff0c;通常不会在这里放置文件 /bin&#xff1a;存放频繁使用的命令,二进制文件&#xff0c;存放了很多用户级的GNU实用工具。 /boot&#xff1a;引导目录&#xff0c;存放引导文件&#xff0c;包含启动Linux所需的核心文件。 /dev&#xff1a;设…

智能驾驶规划控制理论学习05-车辆运动学规划案例分析

目录 案例一——Hybrid A*&#xff08;基于正向运动学&#xff09; 1、基本思想 2、 实现流程 3、启发函数设计 4、分析扩张&#xff08;Analytic Expansions&#xff09; 5、分级规划&#xff08;Hierarchical planning&#xff09; 案例二——State Lattice Planning&…

子矩阵的和 刷题笔记 {二维前缀和}

首先我们的目标是让 s[i][j]表示为其左方和上方形成的矩阵所有元素的和 加上s[i-1][j]和s[i][j-1]后 s[i-1][j-1]部分重复了所以减去 最后加上a[i][j]即可完成目标 s[i][j]s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j]; 然后看题目要求 要求x1,y1,x2,y2围成的小正方形内的元素和…

C/C++工程师面试题(数据库篇)

索引的优缺点 索引是一种支持快速查找特定行的数据结构&#xff0c;如果没有索引&#xff0c;就需要遍历整个表进行查找。用于提高数据检索的速度和效率。 好处&#xff1a; 提高检索速度&#xff1a; 索引可以加快数据的检索速度&#xff0c;因为它们允许数据库系统直接定位到…