Mysql进阶-索引篇(下)

news2024/11/19 5:34:29

 SQL性能分析

SQL执行频率

MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次,通过sql语句的访问频次,我们可以判断到当前数据库到底是以查询为主,还是以增删改为主,从而为数据库优化提供参考依据。 如果是以增删改为主,我们可以考虑不对其进行索引的优化。 如果是以查询为主,那么就要考虑对数据库的索引进行优化了。

0c62ffe6b8c54f18a43282996117fd77.png

慢查询日志 

如果当前数据库是以查询为主,我们可以通过慢查询日志来查看耗时较长的查询,慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有 SQL语句的日志。MySQL的慢查询日志默认没有开启,我们可以查看一下系统变量 slow_query_log。

 慢查询日志默认是关闭的

375261cd484e4dd887613aa728703c2c.png

 开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息,同时重启mysql服务,使配置文件生效

# 开启MySQL慢日志查询开关

slow_query_log=1

# 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志 long_query_time=2

ad7047b43a154514a782a5383c7ba976.png

 查询600万数据的表

eee2fb613cf440e1812862c6adb66c24.png

 毫无疑问出现在慢查询日志上a25b6db262ed4c7fa437a364afaeea05.png

profile详情

show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling 参数,能够看到当前MySQL是否支持profile操作:

#查询是否有profile参数
select @@have_profiling
#查询profile功能是否开启 0表示关闭 1表示开启
select @@profiling

cc3470d26ce14cf1a04b88efebc140cc.png

 可以看到,当前MySQL是支持 profile操作的,但是开关是关闭的。可以通过set语句在 session/global级别开启profiling:

SET profiling = 1;

 执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:

# 查看每一条SQL的耗时基本情况
show profiles;
# 查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
# 查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;

f9c78897baa14e0ba7c47c15a4d63817.png

explain

EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行 过程中表如何连接和连接的顺序。在select语句开头加上explain关键词即可,通过explain各字段的值,我们可以分析出此时的sql语句走不走索引,有没有回表查询等情况,方便我们进行sql优化

7159495b9656426c8f9e8527bcee28f5.png

 Explain 执行计划中各个字段的含义:

字段含义

id

select查询的序列号,表示查询中执行select子句或者是操作表的顺序

(id相同,执行顺序从上到下id不同,值越大,越先执行)。

select_type

表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接 或者子查询)、PRIMARY(主查询,即外层的查询)、 UNION(UNION 中的第二个或者后面的查询语句)、

SUBQUERY(SELECT/WHERE之后包含了子查询)等

type

表示连接类型,性能由好到差的连接类型为NULL、system、const、eq_ref、ref、range、 index、all 。

possible_key

显示可能应用在这次查询的索引,一个或多个。

key

实际使用的索引,如果为NULL,则没有使用索引。

key_len

表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下, 长度越短越好。

rows

MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值, 可能并不总是准确的。

filtered

表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好。

 索引使用

效率验证

准备一张百万数据的表,根据id查询数据,我们可以发现此时耗时仅为0.01秒,这是因为id默认就是主键索引,这是已经有索引的查询情况

5cc44a84f8b1404693b2d776819da01a.png

 根据name字段查询时,此时没有建立name字段的索引,可以看到耗时达到6秒之久

0767130613884f31a5e4fee757174b84.png

建立索引之后,根据name查询,耗时仅有0.01秒,可见索引能大大提升查询效率

16da7e42c69448ba9c458cdc57346665.png

最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始, 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。

以tb_user表为例,此时有idx_user_pro_age_sta这个联合索引,这个联合索引涉及到三个字段,顺序分别为:profession, age,status。

9ee1baad1e4c4c58be19a4f5803f1ac1.png

 对于最左前缀法则指的是,查询时,最左变的列,也就是profession必须存在,否则索引全部失效。 而且中间不能跳过某一列,否则该列后面的字段索引将失效。

explain select * from tb_user where profession = '软件工程' and age = 31 and status
= '0'

 联合索引的三个字段都在联合索引必然生效,只要where条件后面的三个字段都在索引就会生效,与字段的先后顺序无关c1a8a66093d84bfc9e34ecf2cfad24b1.png

 我们尝试profession后面的两个字段逐步减少,会发现联合索引仍然生效,正说明只要索引的最左边的字段在where子句中索引就会生效。从图中我们也可以推测出profession字段索引长度为47、age 字段索引长度为2、status字段索引长度为5。0b8902e66d4549c688b83a70ee02f112.png

 但此时我们将查询条件中的profession去掉,此时联合索引失效。

a14881ef6dad4f5dac66c0dcb5e1577f.png

 如果最左的列存在,但是跳过了中间的列,那么只会中间列之后的索引都不会生效,虽然走了联合索引,但长度只有47,为profession字段索引长度。

aafcdf3aae264c779169b2cabdab9813.png

 范围查询

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。从索引长度可以看到status字段的索引并没有生效

7621835d4b11437abc299473739e755d.png

 但如果我们将范围查询加上等号即≥和≤这种形式,联合索引就生效,在业务允许的情况下,尽可能的使用类似于 >= 或<=,而避免使用 > 或 <,来避免索引失效

f1f5d236c114447e9eaf3942222e9fad.png

 索引失效情况

 索引列函数运算

当根据phone字段进行等值匹配查询时, 索引生效。

56d3207931ac46c18af0f73e8366d7ba.png

 当进行函数运算时,索引就失效,走的是全表扫描

f1f6a41b3f9c45d4abd8d93b2ae703df.png

如果进行的是数值运算,索引仍然生效

d3cc25844ead44fe9a3c6eb24bae6965.png

 字符串不加引号

如果不给phone字段添加引号,造成索引类型不匹配,索引也会失效

7bc723be16744d31bb30e2c049d5ac6b.png

 模糊查询

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

头部模糊查询,走的是全表扫描

8b473af81d804d8bbc15ea39e5118ea5.png

 如果是尾部模糊,则走联合索引,索引生效,如果前后模糊查询,由于前面模糊查询已使索引失效,所以也是索引失效

e15fd297ba7443a58b97516a970bd966.png

 or连接条件

用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会 被用到,因为or前面的用了索引,or后面的列没有索引还是要走全表扫描,mysql优化器就会判断直接全表扫描,避免浪费一次查找索引树的时间

数据分布影响

相同的SQL语句,只是传入的字段值不同,最终的执行计划也完全不一样,这是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不 如走全表扫描来的快,此时索引就会失效。即数据分布情况也会影响索引是否生效

3d2c6523c97444b2a71549f0f26084a9.png

 SQL提示

sql提示就是在执行查询时我们自己指定要使用的索引

 此时我们有 profession这个字段的单列索引

cc3c342851174e1da0aa432f8a380b60.png

 我们可以看到,possible_keys中 idx_user_pro_age_sta,idx_user_pro 这两个 索引都可能用到,最终MySQL选择了idx_user_pro_age_sta索引。这是MySQL自动选择的结果。我们想看到的是走单列索引,毕竟我的mysql我做主,这时候就要用到sql提示啦!38065709f9424d3d924a36153a02c7d1.png

我们可以在select语句时加上use index(索引名)来建议mysql使用我们指定的索引(仅仅是建议,mysql内部还会再次进行评估)

2b20e99a3ad5489cbc1dbc42320bb1f1.png

 上面的use index 仅仅是建议,要是mysql不听怎么办?这时候就需要force index来强制mysql执行我们指定的索引!即使效率可能下降,但爷乐意,千金难买爷乐意,下图我们可以看到正常情况下肯定不会走sta索引的,毕竟我们where子句是根据profession来查的,但通过我们的强制,也能让mysql执行这一索引

28abba46eb4e4adf85ba09ba7271202e.png

覆盖索引

尽量使用覆盖索引,减少select *, 覆盖索引是指查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到。使用覆盖索引能减少能大大提高查询,其原因就是需要返回的列在索引列已经全部找到,不需要回表查询了,这也是mysql优先使用联合索引的原因

前缀索引

介绍

当字段类型为字符串(varchar,text,longtext等)时,有时候需要索引很长的字符串,这会让 索引变得很大,查询时,浪费大量的磁盘IO, 影响查询效率。此时可以只将字符串的一部分前缀,建 立索引,这样可以大大节约索引空间,从而提高索引效率。

 语法

create index idx_xxxx on table_name(column(n)) ;

为tb_user表的email字段,建立长度为5的前缀索引。

fee7b812272f4be8b8e587bf7ce91875.png

 前缀长度

可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值, 索引选择性越高则查询效率越高, 唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。即要保证取得的前缀尽量唯一不重复。

 查询流程

前缀索引相当于二级索引,但他匹配到时,必须回表查询,确认根据前缀索引匹配到行数据的email值跟sql语句的email值是否一样,同时要遍历到链表的下一个元素,看是否与前缀索引匹配,如果是就要重复刚刚的流程然后返回数据,如果不是,直接返回数据即可

88f8c91cfabd49c8a157e95c90721512.png

 单列索引与联合索引

 前文提到的覆盖索引,mysql会优先使用联合索引,以此来减少回表查询,提高查询效率

单列索引:即一个索引只包含单个列。

联合索引:即一个索引包含了多个列。

 索引设计原则

1).针对于数据量较大,且查询比较频繁的表建立索引

2). 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。

3). 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。

4). 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。 5). 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间, 避免回表,提高查询效率

6). 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率,同时索引也会占用硬盘空间。 

7). 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含 NULL值时,它可以更好地确定哪个索引最有效地用于查询。

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

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

相关文章

技术视角下的跑腿小程序开发:关键挑战和解决方案

跑腿小程序作为连接服务提供者和用户的桥梁&#xff0c;面临着诸多技术挑战。本文将聚焦于技术层面的关键挑战&#xff0c;并提供解决方案&#xff0c;以帮助开发者应对技术上的复杂问题。 1. 实时性与性能挑战 挑战&#xff1a; 跑腿小程序需要实时地匹配订单、更新状态和提…

【java学习—十】操作集合的工具类Collections(8)

文章目录 1. 操作集合的工具类&#xff1a; Collections2. 应用3. 查找、替换3.1. max 与 min3.2. 根据Comparator返回max(min) 3.3. frequency 与 replaceAll4. 同步控制 1. 操作集合的工具类&#xff1a; Collections Collections 是一个操作 Set 、List 和 Map 等集合的工具…

从LLM到AIGC,开启AI时代寻宝之旅!

引言 还记得《头号玩家》中男主人公赢得游戏的方式吗——在游戏中漫无目的地闲逛&#xff0c;然后发现彩蛋&#xff0c;获得胜利。 在人工智能领域&#xff0c;有一种新奇性搜索原则的实验&#xff0c;使得机器研究的成功之路恰似寻找彩蛋的道路。比如在不设定“出门”目标的情…

为什么会被【禅道】工具的公司踢出QQ群的反思…………

周末备份Gitlab的代码库&#xff0c;把Gitlab更新到了最新的16.5。顺带看了禅道官网出了最新版本18.8。但是禅道的升级更新并不顺利…………。 先说一下为什么用禅道这个工具&#xff1a; 再使用禅道这个工具前&#xff0c;使用过的工具有QC(Quality Center)、jira&#xff0…

测试工程师简历编写攻略:打造高点击率的简历!

简历是入职职场的一张名片&#xff0c;也是进入职场一块“敲门砖”。从某种角度说&#xff0c;简历也是一张专业人员的说明书。 软件测试人员作为IT行业具有技术含量的职业&#xff0c;一份优秀的简历包含的内容以及如何写好简历尤为重要。接下来从以下两方面来介绍这个话题&a…

Android任务栈和启动模式

Andrcid中的任务栈是一种用来存放Activity实倒的容器。任务最大的特点就是先进后出&#xff0c;它主要有两个基本操作&#xff0c;分别是压栈和出栈。通常Andaid应用程序都有一个任务栈&#xff0c;每打开一个Activity时&#xff0c;该Activity就会被压入任务栈。每销毁一个Act…

eclipse Occurrence

eclipse Occurrence Occurrence of initUi2_setData_99 Window->Preferences->General->Editors->Text Editors->Annotations->Occurrences 个人感觉最好用的颜色&#xff1b; 边线&#xff0c;正文都可以看得清楚

Elasticsearch(一)---介绍

简介 Elasticsearch是一个基于Lucene的实际的分布式搜索和分析引擎。设计用于云计算中&#xff0c;能够达到近实时搜索&#xff0c;稳定&#xff0c;可靠&#xff0c;快速&#xff0c;安装使用方便。基于RESTful接口。 官网地址&#xff1a;Elasticsearch 平台 — 大规模查找…

开关电源测试方案分享:电源纹波及噪声测试方法、测试标准

纹波及噪声影响着设备的性能和稳定性&#xff0c;是开关电源测试的重要环节。通过电源纹波噪声测试&#xff0c;检测电源纹波情况&#xff0c;从而提升开关电源的性能。纳米软件开关电源自动化测试软件助力纹波和噪声测试&#xff0c;提升测试效能。 开关电源纹波及噪声测试方法…

一文分享提升嵌入式代码的分析工具

当前标准的C语言编译器存在普遍只能找出代码中潜在的缺陷&#xff0c;而对程序方案设计并没有效。 使用静态代码分析器有助于提升固件和捕获编译器难以察觉的问题。 1、用于嵌入式的常见代码静态分析工具 代码静态分析工具&#xff0c;顾名思义就是对代码进行静待分析&#…

【Python图像处理局部放大】输入图像,选择两处不同的区域进行放大操作,然后将原始图像、处理后的两个区域以及标记合成新图像进行展示

NeRF-w 渲染后的图像效果的定性对比&#xff0c;对局部放大以观察细节效果。如下 对单张渲染后的图像&#xff0c;选择指定区域并进行放大操作&#xff0c;然后将原始图像、处理后的两个区域以及标记连线的新图像&#xff0c;如下图 代码 from PIL import Image, ImageDraw# 读…

预制件二维码怎么做

凡尔码的二维码管理系统不仅提供了高效便捷的二维码生成功能&#xff0c;还配备了一套完善的预制构件管理方案。通过扫描二维码&#xff0c;用户可以查看预制构件的详细信息&#xff0c;包括项目名称、构建名称、安装位置、重量、生产日期、生产单位、产品出厂检验材料、尺寸等…

《2023整车操作系统发展趋势研究》丨附下载

✦ ✦✦ ✦✦ ✦✦ ✦ 1996年&#xff0c;Gartner提出SOA其核心思想在于“通过将庞大的计算系统按照实际业务拆分为独立部署的大小合适的功能模块&#xff0c;提高功能单元的复用性&#xff0c;降低产品开发的复杂度和成本”。 如今&#xff0c;软件定义汽车领域引入SOA&…

竟然还有人不知道这个app?注册即可在线管理各类地理空间数据

「四维轻云」是一款轻量化的地理空间数据管理云平台&#xff0c;具有项目管理、数据浏览、数据分享、场景编辑、素材库等功能。 此外&#xff0c;用户还可以在应用商店及官网下载安装“四维轻云”APP。安装完成后&#xff0c;用户可以在APP中管理、查看及分享倾斜摄影模型、激…

一文看懂完整的研究生生活规划

很多人在刚从本科步入研究生生活的时候,总是对于自己三年的研究生生活没有清晰的规划,总是在各种浪费时间,没有拿到想要的东西,也没有学到想学的东西,亦或是没有找到理想的工作,最后草草的毕业。这个时候我们就应该对于自己的研究生生活有个清晰的规划,帮助我们不留遗憾…

集群/堆叠的常用部署实施方式,你会吗?

你们好&#xff0c;我的网工朋友。 交换机的连接方式大家应该都知道吧&#xff0c;一共有三种&#xff0c;分别是&#xff1a;级联、堆叠和集群。 级联一般用来实现多台交换机之间的互相连接。 堆叠和集群&#xff0c;就总有网工把这两给搞迷糊了。 堆叠就是将多台支持堆叠特…

python_PyQt5日周月K线纵向对齐显示_1_数据处理

目录 写在前面&#xff1a; 图形结果显示&#xff1a; 数据设计&#xff1a; 代码&#xff1a; 从日数据中计算周数据、月数据 生成图形显示需要的数据格式 写在前面&#xff1a; “PyQt5日周月K线纵向对齐显示”&#xff0c;将分三篇博文描述 1 数据处理。将数据处理成…

Python学习——Day12

目录 一、实例方法、类方法、静态方法 1.1实例方法 1.2类方法 1.3静态方法 1.4实例 二、 __slots__ 三、错误和异常 3.1语法错误 3.2异常 3.3异常处理 一、实例方法、类方法、静态方法 1.1实例方法 实例方法入参第一个值&#xff0c;默认self指代当前调用的对象,不建…

数字转型下的保险业:可视化大屏的光明未来

在当今不确定性充斥的世界中&#xff0c;保险行业扮演着关键的社会角色。无论是财产保险、健康保险还是生命保险&#xff0c;它们都提供了一种安全网&#xff0c;帮助个人和企业在不可预测的风险面前保护自己。然而&#xff0c;随着信息时代的来临&#xff0c;数据变得愈发重要…

FreeRTOS系统下看门狗定时器的使用总结

文章目录 前言定时器分类何为看门狗定时器 系统复位系统级看门狗SWDT的使用1.看门狗配置2、独立监测多任务方式 前言 本文记录自己使用看门狗定时器的过程&#xff0c;起因是系统不知名原因总是跑挂&#xff0c;查了很久找不到原因&#xff08;排除了变量溢出、中断冲突等&…