【MySQL进阶】索引性能分析

news2024/12/24 2:59:48

1. 索引语法

  1. 创建索引:

​ 语法格式:create [unique|fulltext] index index_name on table_name(index_col_name...);

  1. 查看索引:

​ 语法格式:show index from table_name;

  1. 删除索引:

​ 语法格式:drop index index_name on table_name;

案例演示
先来创建一张表 tb_user,并且查询测试数据。
数据准备好了之后,接下来,我们就来完成如下需求:
A. name字段为姓名字段,该字段的值可能会重复,为该字段创建索引。
语法格式:create index idx_user_name on tb_user(name);
B. phone手机号字段的值,是非空,且唯一的,为该字段创建唯一索引。
语法格式:create unique index idx_user_phone on tb_user(phone);
C. 为profession、age、status创建联合索引。
语法格式:create index idx_user_pro_age_sta on tb_user(profession,age,status);
D. 为email建立合适的索引来提升查询效率。
语法格式:create index idx_user_email on tb_user(email);

2. SQL性能分析

2.1 SQL执行频率

我们可以在客户端中使用show [session|global] status查看服务器的状态信息,通过以下指令就可以查看当前数据库对应执行SELECT、UPDATE、DELETE、INSERT的操作次数
语法格式:SHOW GLOBAL STATUS LIKE 'Com_______';
image.png
相关字段信息如下:

  • Com_select:进行select操作的次数
  • Com_insert:进行insert操作的次数
  • Com_update:进行update操作的次数
  • Com_delete:进行delete操作的次数

💡 提示:通过上述指令我们就可以基本判断当前数据库是执行查询操作居多还是进行增删改等操作居多,如果是查询操作居多后续就可以针对性的进行索引SQL优化!

2.2 慢查询日志

慢查询日志:当某个查询SQL执行的时长超过指定的阈值(long_query_time)时则会将该条SQL记录到慢查询日志(slow_query_log_file)当中,相关命令如下:

  1. 查看慢查询日志是否开启:

语法格式:show variables like 'slow_query_log';
image.png

  1. 如何开启慢查询日志:

答:在MySQL配置文件(windows为my.ini,Linux系统为my.cnf)当中配置以下内容,随后重启MySQL服务器即可

# 慢查询日志相关
slow_query_log = 1 # 开启慢查询日志
long_query_time = 2 # 慢查询阈值(默认为10)
# slow_query_log_file = '' # 慢查询日志文件位置 
  1. 查看配置内容是否生效:
  • 查看慢查询是否开启:show variables like 'slow_query_log';
  • 查看慢查询时间阈值:show variables like 'long_query_time';
  • 查看慢查询日志文件位置:show variables like 'slow_query_log_file';

2.3 profile详情

Profile:profile详情可以帮助我们查看某个SQL具体的执行阶段耗时,相关操作如下:

  1. 查看当前MySQL是否支持profile:

语法格式:select @@have_profiling;

  1. 查看当前MySQL是否开启profiling:

语法格式:select @@profiling;
image.png
如果显示为0证明没有开启!

  1. 开启profiling操作:

语法格式:set profiling=1;
接下来我们可以执行一条SQL语句,比如select * from tb_user;
然后使用show profiles;查看所有SQL语句的耗时详情
image.png
如果想要查看更加具体的耗时信息,可以使用如下SQL语句:show profile for query query_id;
image.png

2.4 explain执行计划

执行计划:我们可以使用执行计划查看某个查询SQL的执行信息,包括表是如何连接以及表连接的顺序,语法格式如下:
语法格式:explain/desc select 字段列表 from 表名 where 条件;
image.png
其中各个字段含义如下:

  • id:select查询的的序列号,表示操作表的顺序(id值越大越先执行,相同则从上到下依次执行)
  • select_type:表示select的类型,如果是simple表示单表操作(没有任何子查询和表连接),primary表示主查询,subquery表示子查询
  • type:表示连接类型,从好到坏依次为:null、system、const、eq_ref、ref、range、index、all
  • possible_key:可能使用到的索引,一个或者多个
  • key:实际使用到的索引,如果为null则没有使用索引
  • key_len:索引中使用到的字节数
  • rows:MySQL认为要执行查询的行数,并不总是精确的
  • filtered:表示返回结果的行数占需要读取行数的百分比,值越大越好

3. 索引使用原则

3.1 最左前缀法则

最左前缀法则:如果构建了一个联合索引,此时需要遵循最左前缀原则:即查询的时候要从联合索引最左边的列开始,否则索引失效;并且如果中间跳跃某一列,则后面部分的索引失效。
我们查看tb_user表中的索引信息:
image.png
可以发现我们创建了一个名称为idx_user_pro_age_sta的联合索引,联合的字段分别是profession、age、status,因此查询过程中想要使用联合索引必须遵循最左前缀原则。如果查询条件没有profession则索引失效,如果中间跳跃某一索引列则后面的索引失效!下面我们就来进行举例:
使用联合索引:

  1. case1:查询条件包括profession、age、status字段

image.png
此时索引长度为54,使用到了全部的联合索引

  1. case2:查询条件只包括profession和age字段

image.png
此时虽然key字段表明仍然使用到了该联合索引,但是key_len变为了49,证明只用到了部分索引!即status字段的索引长度为54 - 49 = 5

  1. case3:查询条件只包括profession字段

image.png
此时key字段表明使用到了该联合索引,但是key_len变为了47,证明只用到了部分索引!即age字段的索引长度为49 - 47 = 2
联合索引失效:

  1. case1:查询条件只使用age、status字段

image.png
此时key为null并且type为all证明并没有走索引,而是进行了全表扫描,因此没有使用到联合索引最左边的列,不符合"最左前缀法则",索引失效!

  1. case2:查询条件使用profession和status字段

image.png
此时根据key_len我们可以推断出只使用到了profession这个字段的索引,因为跳过了中间的索引列age,因此右侧索引全部失效!

❓ 提问:如果执行语句select * from tb_user where status = ‘0’ and age = 31 and profession = ‘软件工程’,是否会走联合索引?索引长度是多少?
正确答案:符合最左前缀原则,索引长度为54,因为是否遵循最左前缀法则与SQL定义的排列顺序无关,内部查询优化器会自动进行分析优化!

3.2 范围查询

现象:当在使用联合索引的过程中,使用到了范围查询(>,<)此时范围查询右侧索引失效!
举例:执行以下SQL语句:explain select * from tb_user where profession = '软件工程' and age > 31 and status = '0';查看执行计划:
image.png
此时key证明使用到了联合索引,但是key_len表明索引长度为49即(只使用到了profession和age字段的索引),范围查询右侧的status字段索引失效!
解决方案:尽量使用>=,<=之类的范围查询
image.png

3.3 索引失效情况

3.3.1 索引列运算

原则:如果在索引列上进行了运算,则索引失效!
查看当前tb_user表中的索引情况:发现在列phone上有一个单列索引
image.png
需求:查询phone字段最后两位是’15’的所有用户信息
image.png
此时我们发现type字段为ALL证明没有使用索引,而是进行了全表扫描,因为索引列phone参与了运算!

3.3.2 字符串不加引号

原则:如果索引列为varchar等字符类型,但是查询时没有使用引号则索引失效!

  • case1:字符串类型使用引号

image.png

  • case2:字符串类型不使用引号

image.png
上述结果中我们可以看出,虽然两者都可以正常查询出结果,但是仅仅是将status字段查询条件由’0’变成了0,导致了status字段索引失效!

3.3.3 模糊查询

原则:在使用LIKE等模糊查询时,如果是尾部模糊匹配则索引不会失效,但是如果是头部模糊匹配则索引失效!

  • case1:尾部模糊匹配

image.png

  • case2:头部模糊匹配

image.png

  • case3:尾部头部均模糊匹配

image.png
上述结果中我们可以看出,尾部模糊匹配并不会造成索引失效!但是只要使用到了头部模糊匹配就会造成索引失效!

3.3.4 or连接条件

原则:在使用or语句时,只有两侧都使用到了索引才会生效

  • case1:当age没有建立索引时

image.png
image.png
此时无论是使用id主键索引还是phone唯一索引,因为age字段没有索引,因此or条件不符合两侧均使用索引的情况,此时索引失效!

  • case2:当age建立索引时

image.png
此时当我们将age字段添加索引时,继续执行上述执行计划,此时可以看到索引生效了,因为or条件两侧均使用了索引

3.3.5 数据分布影响

原则:如果MySQL评估全表扫描比索引更快时,索引失效!

  • case1:查询age >= 1的所有用户

image.png

  • case2:查询age >= 40的所有用户

image.png
此时我们可以发现上述两条SQL语句结构完全一样,只是传入的参数不一样,但是age>=1进行了全表扫描,age>=40则使用索引查询,这是因为当前表中大部分数据都是符合age>=1的,因此MySQL预估走全表扫描的时间效率高于通过索引查询!

3.4 SQL提示

背景引入:
当前profession是存在联合索引的:
image.png
但是如果我们给profession加上一个单列索引,继续执行这条SQL语句会走哪个索引呢?
image.png
可以发现,此处possible_keys显示可能使用的索引为联合索引和单列索引,但是MySQL评估之后最终选择了联合索引,那么我们可以指定让MySQL使用哪种索引吗?因此引入了SQL提示:
SQL提示:是优化数据库的一个手段,简单来说就是在SQL执行过程中加入人为指定的一些提示

  1. use index:建议MySQL使用何种索引(有可能MySQL并不接受你的建议)

image.png

  1. ignore index:忽略指定的索引

image.png

  1. force index:强制使用某种索引

image.png

3.5 覆盖索引

覆盖索引:指的是查询过程中使用到了索引,并且需要返回的列恰好都在索引中能够全部找到,因此尽量不要在查询时使用select *类似的语法,否则会造成回表查询,效率低下!
下面我们就来看看以下两条SQL语句的执行计划:
case1:查询id、profession、age、status字段
image.png
case2:查询全部字段
image.png
我们需要注意执行计划当中的extra字段:

  1. 如果列值为Using where、Using index说明需要返回的字段都在索引中,因此无需回表查询
  2. 如果列值为Using Index condition说明需要返回的字段并不完全包含在索引中,需要根据id回表查询

总结
由于我们建立了联合索引(profession、age、status),该索引是一个二级索引,在查询时叶子节点下包含该数据的主键id信息,当需要查询id、profession、age、status等字段内容时,只需要查询二级索引即可获取全部信息,但是如果需要查询以外的字段内容,则需要根据id主键回表查询聚集索引,性能相对较差

❓ 提问: 一张表, 有四个字段(id, username, password, status), 由于数据量大, 需要对 以下SQL语句进行优化, 该如何进行才是最优方案: select id,username,password from tb_user where username = ‘itcast’;
正确答案:需要对username和password建立联合索引,对应SQL为create index idx_user_name_pass on tb_user(username, password),此时就可以避免回表查询,且使用到了该联合索引

3.6 前缀索引

3.6.1 基本概念

前缀索引:有时候当我们需要存储文章内容时可能会使用到varchar、text等文本类型,但是如果存储内容很多,此时索引占用的存储空间就会非常大,而且还会导致IO查询效率变低。有时候我们可以根据这些字符串的一部分前缀作为索引,节省空间的同时提升效率。
语法格式create index idx_name on table_name(index_col_name(n));
例如当前我们尝试给tb_user表中的email字段添加长度为5的前缀索引:
image.png

3.6.2 索引选择性

那么我们应该如何选择合适的索引前缀长度呢?可以根据索引的选择性进行分析:选择性就是不重复的索引记录数和数据表总数的比值。索引选择性越高,对应的查询效率就越高(最高的选择性就是1)
我们可以使用诸如下面的SQL语句查看当前前缀长度为n时对应的索引选择性:
语法格式:select count(distinct substr(email,1,5)) / count(*) from tb_user;
image.png
此时相对于此表来说,选择前缀长度为5能保持较高的选择性并且占用较低的存储空间

4. 索引设计原则

这里简单介绍构建索引时应当遵守的原则:

  1. 索引适用于那些数据量较大并且查询操作较为频繁而增删改操作不频繁的表
  2. 索引常用于那些经常用于进行where、group by、order by的字段
  3. 索引列应该挑选区分度较高的字段,尽量构建唯一索引,区分度越高,索引查询性能越好
  4. 如果是字符串类型的列并且字段长度较大,可以考虑使用前缀索引
  5. 尽量使用联合索引和非单列索引,因为联合索引很多情况可以使用到覆盖索引,避免回表查询
  6. 要控制索引的数量,索引并不是越多越好,索引越多导致维护的成本也会升高,并且影响增删改的效率
  7. 如果索引列不能存储null值,请在创建表时使用not null进行约束。以便于查询优化器更好确定使用哪个索引查询

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

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

相关文章

Spring Boot实现License生成和校验

1.License应用场景 在我们向客户销售商业软件的时候&#xff0c;常常需要对所发布的软件实行一系列管控措施&#xff0c;诸如验证使用者身份、软件是否到期&#xff0c;以及保存版权信息和开发商详情等。考虑到诸多应用场景可能处于离线环境&#xff0c;无法依赖网络进行实时认…

5.数据结构-c/c++二叉树详解(上篇)(遍历方法,完全二叉树)

目录 一. 二叉树的基本介绍 1.2 满二叉树 1.3 完全二叉树 1.4 搜索二叉树 1.5 平衡二叉搜索树 二. 二叉树的常用操作 2.1 二叉树的定义 2.2 创建一个新的节点 2.3 构建一颗树 2.5 销毁一棵树 三.二叉树的前序&#xff0c;中序&#xff0c;后序&#xff0c;层序遍历方…

day-47 子集

思路 利用深度优先遍历算法&#xff0c;对于每个数有选或不选两种抉择&#xff0c;每次遍历到idslen时将p加入答案中 解题过程 选中当前数字&#xff0c;调用dfs函数之后记得还原 Code class Solution {public int len;public List<List<Integer>> listnew Arra…

51单片机的智能台灯设计【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块DS1302时间模块光敏传感器模块人体红外模块按键等模块构成。适用于智能台灯、自动调节灯光亮度等相似项目。 可实现基本功能: 1、LCD1602实时显示北京时间、环境光照强度、手动/自动模式、台灯亮度等信息&#xff1…

笔记整理—uboot番外(1)命令体系

在uboot启动进行命令行的环境下&#xff0c;当输入命令时&#xff0c;将会对命令进行先解析后执行的操作。 uboot/common/cmd_xxx.c 其中就有多个命令体系&#xff08;mian.c和commann.c&#xff09; uboot每个命令都对应了一个相关的函数&#xff0c;由此实现的命令体系与…

字符统计及重排

题目描述 给出一个仅包含字母的字符串&#xff0c;不包含空格&#xff0c;统计字符串中各个字母(区分大小写)出现的次数 并按照字母出现次数从大到小的顺序。输出各个字母及其出现次数。 如果次数相同&#xff0c;按照自然顺序进行排序&#xff0c;且小写字母在大写字母之前&a…

2024年【氧化工艺】考试及氧化工艺最新解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 氧化工艺考试考前必练&#xff01;安全生产模拟考试一点通每个月更新氧化工艺最新解析题目及答案&#xff01;多做几遍&#xff0c;其实通过氧化工艺操作证考试很简单。 1、【单选题】 废水经生物脱氮工艺、吹脱工艺等…

如何自学通过软考中级系统集成项目管理工程师?

虽然中级项目管理工程师&#xff08;以下简称中项&#xff09;考试相对较容易&#xff0c;但如果你是零基础&#xff0c;不建议完全依靠自学。 中项属于软考的"信息系统"专业&#xff0c;是中级资格。熟悉软考的人都知道&#xff0c;软考包括初级、中级、高级3个级别…

python-uinput虚拟输入

文章目录 python-uinput虚拟输入背景库简介&#xff1a;什么是python-uinput&#xff1f;安装指南&#xff1a;如何获取这个强大的工具&#xff1f;快速上手&#xff1a;五个核心函数的介绍与使用1. 创建虚拟设备2. 模拟键盘输入3. 模拟鼠标移动4. 模拟鼠标点击5. 模拟触摸屏操…

【粒子群算法PSO】基本原理及多种改进方法

【粒子群算法Matlab仿真定制】&#xff1a; QQ&#xff1a;491052175 1. 粒子群算法的发展趋势 粒子群算法&#xff0c;又称粒子群优化算法&#xff08;Particle swarm opyimization, PSO&#xff09;&#xff0c;是近年来新发展起来的进化算法。该算法和模拟退火算法相似&a…

Vue(十二) Vuex、四个map方法的使用、Vuex模块化+namespace命名空间

文章目录 一、Vuex前言&#xff1a;求和案例1. 搭建Vuex环境2. 基本使用3. 常见疑惑4. getters5. 四个map方法的使用(1) mapState(2) mapGetters(3) mapActions(4) mapMutations 6. 模块化命名空间namespace6.1 模块化6.2 模块化后读取数据 一、Vuex Vuex是一个Vue插件&#x…

FPGA与高速ADC接口简介

引言&#xff1a;本文介绍FPGA与高速ADC接口方式和标准以及JESD204与FPGA高速串行接口。 1. 高速ADC与处理器互联需要权衡的因素 如图1所示&#xff0c;ADC模数转换器可以与微控制器、DSP、FPGA以及ASIC均可以实现互联&#xff0c;在进行选择时&#xff0c;需要考虑以下因素&…

强化学习实操入门随笔

碎碎念&#xff1a;经过思考&#xff0c;打通底层逻辑&#xff0c;我认为未来ai的功能是在沟通领域代替人&#xff0c;未来人-人模式&#xff08;媒介是死的语言&#xff0c;比如看古人留下的文字、聊天的暂时不在&#xff09;会变成人-ai替身-人模式&#xff08;符合本人想法的…

上市公司财务数据分析系统

前言 1.拟解决的关键问题或技术: 本研究旨在解决企业在财务管理方面的主要问题,即如何通过对财务数据进行深度挖掘,实现对未来财务趋势的预测和风险的识别。具体地,该研究将重点解决以下问题: 1.构建有效的财务指标体系、设计合理的特征工程和指标构建方法,以充分反映…

Java基于小程序公考学习平台的设计与实现

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

QT实现简易文件夹

使用UI界面实现简易文件夹 1、实现功能 1、双击文件夹&#xff0c;进入文件夹的下一层 2、点击回退按钮、返回上一级 3、如果是文本文件、则调用记事本的程序、显示文本内容 2、widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDir>…

《深度学习》OpenCV 图像边缘检测 算法解析及代码演示

目录 一、图像边缘检测 1、什么是边缘检测 2、常用的边缘检测算法 1&#xff09;Sobel算子 2&#xff09;Scharr 算子 3&#xff09;Canny边缘检测算法 4&#xff09;Laplacian算子 3、边缘检测流程 1&#xff09;预处理 2&#xff09;计算梯度 3&#xff09;非极大值抑制 …

微型直线导轨高精度运行的工作原理

微型导轨是一种用于高精度定位和运动控制的传动装置&#xff0c;常用于微小化、高精密度化的机械设备中&#xff0c;如IC制造设备、半导体设备、高速移载的设备、精密测量、检测仪器、医疗设备、X-Y table&#xff0c;以及高速皮带驱动的设备等小型化设备。 微型导轨的构成相对…

Quartz.Net_持久化

简述 通常而言&#xff0c;Quartz.Net的数据默认是存储在运存中的&#xff0c;换言之&#xff1a;断电即失。所以在默认情况下&#xff0c;当系统重启后&#xff0c;原先的所有任务、触发器、调度器都会失效 为避免上述情况的发生&#xff0c;可以对Quartz.Net进行持久化设置…

支持函数库功能,支持对接豆包、腾讯混元、Amazon Bedrock等模型供应商,MaxKB v1.5.0版本发布

2024年9月2日&#xff0c;MaxKB开源知识库问答系统正式发布v1.5.0版本。 在v1.5.0社区版中&#xff0c;应用编排方面&#xff0c;MaxKB新增函数库功能&#xff0c;支持用户在应用编排时调用函数&#xff1b;模型管理方面&#xff0c;MaxKB新增对豆包、腾讯混元和Amazon Bedroc…