MySQL索引优化实战一

news2024/12/23 10:32:49
#插入一些示例数据
 drop procedure if exists insert_emp;
 delimiter ;;
 create procedure insert_emp()
 begin
 declare i int;
 set i=1;
 while(i<=100000)do
 insert into employees(name,age,position) values(CONCAT('tqq',i),i,'dev');
 set i=i+1;
 end while;
 end;;
 delimiter ;
 call insert_emp();
 
 EXPLAIN SELECT * FROM employees WHERE name > 'LiLei' AND age = 22 AND position ='manager';

1、联合索引第一个字段用范围不会走索引

 EXPLAIN SELECT * FROM employees WHERE name > 'LiLei' AND age = 22 AND position ='manager';

在这里插入图片描述
结论:联合索引第一个字段就用返回查找不会走索引,MySQL内部可能觉得第一个字段就用范围,结果集应该很大,回表效率不高,还不如走全表扫描。

2、强制走索引

 EXPLAIN SELECT * FROM employees force index(idx_name_age_position) WHERE name > 'LiLei' AND age = 22 AND position ='manager';

在这里插入图片描述
结论:虽然使用了强制走索引让联合索引第一个字段范围查找也走索引,扫描的行rows看上去也少了点,但是最终查找效率不一定比全表扫描高,因为回表效率不高

 ‐‐ 关闭查询缓存
 set global query_cache_size=0;
 set global query_cache_type=0;
 ‐‐ 执行时间0.333s
 SELECT * FROM employees WHERE name > 'LiLei';
 ‐‐ 执行时间0.444s
 SELECT * FROM employees force index(idx_name_age_position) WHERE name > 'LiLei';

3、覆盖索引优化

查询结果集符合最左前缀原则,减少回表。

 EXPLAIN SELECT name,age,position FROM employees WHERE name > 'LiLei' AND age = 22 AND position ='manager';

在这里插入图片描述

4、in和or在表数据量比较大的时候会走索引,在表记录不多的情况下会选择全表扫描

 EXPLAIN SELECT * FROM employees WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';

在这里插入图片描述

 EXPLAIN SELECT * FROM employees WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';

在这里插入图片描述
做一个小实验,将employees 表复制一张employees_copy的表,里面保留两三条记录

 
 EXPLAIN SELECT * FROM employees_copy WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';
 
 EXPLAIN SELECT * FROM employees_copy WHERE name in ('LiLei','HanMeimei','Lucy') AND age = 22 AND position ='manager';

在这里插入图片描述
在这里插入图片描述

5、 like KK% 一般情况都会走索引

  EXPLAIN SELECT * FROM employees WHERE name like 'LiLei%' AND age = 22 AND position ='manager';

在这里插入图片描述

	EXPLAIN SELECT * FROM employees_copy WHERE name like 'LiLei%' AND age = 22 AND position ='manager';

在这里插入图片描述

索引下推(Index Condition Pushdown,ICP)

like KK%其实就是用到了索引下推优化
对于辅助的联合索引(name,age,position),正常情况按照最左前缀原则,SELECT * FROM employees WHERE name like ‘LiLei%’ AND age = 22 AND position =‘manager’ 这种情况只会走name字段索引,因为根据name字段过滤完,得到的索引行里的 age 和 position是无序的,无法很好的利用索引。在MySQL5.6之前的版本,这个查询只能在联合索引里匹配到名字是 ‘LiLei’ 开头的索引,然后拿这些索引对应的主键逐个回表,到主键索引上找出相应的记录,再比对age和position这两个字段的值是否符合。MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,可以有效的减少回表次数。使用了索引下推优化后,上面那个查询在联合索引里匹配到名字是 ‘LiLei’ 开头的索引之后,同时还会在索引里过滤age和position这两个字段,拿着过滤完剩下的索引对应的主键id再回表查整行数据。
索引下推会减少回表次数,对于innodb引擎的表索引下推只能用于二级索引,innodb的主键索引(聚簇索引)树叶子节点上保存的是全行数据,所以这个时候索引下推并不会起到减少查询全行数据的效果。

为什么范围查找MySQL没有用索引下推优化?

估计应该是Mysql认为范围查找过滤的结果集过大,like KK% 在绝大多数情况来看,过滤后的结果集比较小,所以这里MySQL选择给 like KK% 用了索引下推优化,当然这也不是绝对的,有时like KK% 也不一定就会走索引下推。

MySQL如何选择合适的索引

EXPLAIN select * from employees where name > 'a';

没走索引
在这里插入图片描述

EXPLAIN select * from employees where name > 'zzz';
 

走了索引
在这里插入图片描述
MySQL会计算走索引和不走索引的成本,如果走索引会看走那个索引花费的成本小。

trace工具用法

set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启trace
select * from employees where name > 'a' order by position;
SELECT * FROM information_schema.OPTIMIZER_TRACE;

常见sql深入优化

order by 与group by 优化
在这里插入图片描述
上图用了索引,如果Extra中用了Using filesort就是没有用索引

case 8:
数据量大所以走了全表扫描。
在这里插入图片描述
可以使用覆盖索引优化:
在这里插入图片描述

优化总结:

1、MySQL支持两种方式排序:indexfilesort,Using index MySQL扫描索引本身完成排序,效率高,filesort效率低。
2、order by 会使用Using index的两种情况:

  • order by 使用索引最左前列
  • 使用where 子句与order by 子句条件组合满足索引最左前列
    3、尽量在索引类上完成排序,遵循索引建立时的最左前缀法则;
    4、如果order by的条件不在索引列上,就会产生 Using filesort
    5、能用覆盖索引尽量用覆盖索引
    6、group by 与 order by 很类似,实质就是先排序后分组。遵循索引创建最左前缀法则,对于group by 的优化如果不需要排序的加上order by null禁止排序。where高于having,能写在where中的限定条件不要在having中限定。

Using filesort文件排序原理详解

filesort文件排序方式【单路排序、双路排序(回表)】

  • 单路排序
    一次性取出所有的满足条件行的字段,在sort buffer中排序,trace工具可以看到sort_mode信息里显示<sort_key,additional_fields> 或则 <sort_key,packed_additional_fields>
  • 双路排序(回表)
    首先根据相应的条件取出相应的排序字段和可以直接定位行数据的ID,然后在sort suffer中进行排序,排序完再通过ID回表取出其他需要的字段。trace工具可以看到sort_mode信息里显示<sort_key,rowid>

MySQL通过比较系统变量max_length_for_sort_data(默认1024字节)的大小和需要查询的字段总大小来判断使用那种模式:

  • 如果字段的总长度小于max_length_for_sort_data,那么使用单路排序;
  • 如果字段的总长度大于max_length_for_sort_data,那么使用双路排序。
explain select * from employee where name = ‘tqq’ order by  position

单路排序详细过程:
1、从索引name找到第一个满足name=‘tqq’ 条件的主键id;
2、根据主键id取出整行,取出所有字段的值,存入sort Buffer中
3、从索引name找到下一个满足name = 'tqq’条件的主键id;
4、重复步骤2、3直到不满足name=‘tqq’
5、对sort buffer 中的数据按照字段position进行排序
6、返回结果给客户端

双路排序详细过程:
1、从索引name找到第一个满足name=‘tqq’ 条件的主键id;
2、根据主键id取出整行,把排序字段position和主键id两个字段放到sort buffer中
3、从索引name取出下一个满足name = 'tqq’记录的主键
4、重复步骤2、3直到不满足name=‘tqq’
5、对sort buffer中的字段position和主键id按照字段position进行排序
6、遍历排序好的id和字段position,按照id的值回到原表中取出所有字段返回给客户端

索引的设计原则

1、代码先行,索引后上
等业务主体功能开发完毕,把设计到该表相关的SQL拿出来分析之后再建立索引。
2、联合索引尽量覆盖条件
尽量少建单值索引。可以设计1-3个联合索引,让每一个联合索引都尽量去包含SQL语句里的where、order by 、group by 的字段,联合索引的字段顺序尽量满足SQL查询的最左前缀原则。
3、不要在小基数字段上建立索引
索引基数就是这个字段在表中总共有多少个不同的值。比如性别。
4、长字符串我们可以采用前缀索引
对于varchar(255)的大字段可能会比较占用磁盘空间,可以对字段的前20个字符建立索引,对这个字段里的每个值的前20个字符放在索引树中,类似key index(name(20),age,position),这样就不能使用order by 了
5、where与order by 冲突的时候优先where
一般这种时候往往都是让where条件去使用索引快速搜索出来一部分指定的数据,接着再进行排序。因为大多数情况基于索引进行where筛选往往可以最快速读筛选出你想要的数据,然后排序的成本可能会小很多
6、基于慢SQL查询做优化
可以根据监控后台的一些慢SQL,针对慢SQL查询做特定的索引优化
慢SQL查询:https://blog.csdn.net/qq_40884473/article/details/89455740

设计索引的核心思想是:尽量利用一两个复杂的多字段联合索引,抗下80%以上的查询,然后用一两个辅助索引尽量抗下剩余的一些非典型查询。保证大数据量表的查询尽可能多的都能充分利用索引,这样就能保证查询速读和性能了。

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

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

相关文章

linaro交叉编译工具链下载与使用笔记

笔记 文章目录 笔记确定目标 &#xff08;aarch64&#xff09;选择版本&#xff08;7.5&#xff09;选择目标&#xff08;aarch64-linux-gnu&#xff09;下载地址工具链&#xff08;gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz&#xff09;编译测试 &#xff08…

WIFI模块(esp-01s)实现天气预报代码实现

目录 前言 实现图片 一、串口编程的实现 二、发送AT指令 esp01s.c esp01s.h 三、数据处理 1、初始化 2、cjson处理函数 3、核心控制代码 四、修改堆栈大小 前言 实现图片 前面讲解了使用AT指令获取天气与cjson的解析数据&#xff0c;本章综合将时间显示到屏幕 一、…

Python超级详细的变量命名规则

Python 需要使用标识符给变量命名&#xff0c;其实标识符就是用于给程序中变量、类、方法命名的符号&#xff08;简单来说&#xff0c;标识符就是合法的名字&#xff09;。 Python 语言的标识符必须以字母、下画线&#xff08;_&#xff09;开头&#xff0c;后面可以跟任意数目…

Python单元测试之道:从入门到精通的全面指南

在这篇文章中&#xff0c;我们会深入探讨Python单元测试的各个方面&#xff0c;包括它的基本概念、基础知识、实践方法、高级话题&#xff0c;如何在实际项目中进行单元测试&#xff0c;单元测试的最佳实践&#xff0c;以及一些有用的工具和资源 一、单元测试重要性 测试是软…

ELk部署,保姆级教学超详细!!!

Elk&#xff08;Elasticsearch, Logstash, Kibana&#xff09;是一套日志收集、存储和展示方案&#xff0c;是由Elastic公司开发的开源软件组合。 Elasticsearch&#xff1a;是一个分布式的搜索和分析引擎。它能够处理大量的数据&#xff0c;并提供快速、准确的搜索结果&#x…

在线 SQL 模拟器SQL Fiddle使用简介

在线 SQL 模拟器SQL Fiddle使用简介 有时候&#xff0c;我们想去验证 SQL语句&#xff0c;却缺少数据库环境&#xff0c;那该怎么办呢&#xff1f; 这时候在线 SQL 模拟器就有了用武之地。SQL 模拟器免安装&#xff0c;可以在网页直接运行 SQL 。 SQL Fiddle 支持 MySQL、Orac…

Stable Diffusion绘画系列【4】:可爱盲盒风人物

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

数据结构——链式二叉树的实现(详解)

呀哈喽。我是结衣。 不知道大家的递归学到怎么样呢&#xff1f;如果大家的递归功底不是很好&#xff0c;那么我相信在学完这篇文章后大家一定会对递归有一个更深层次的了解的。 构造链式二叉树 在学习二叉树的基本操作前&#xff0c;需先要创建一棵二叉树&#xff0c;然后才能…

国标GB28181安防监控平台EasyCVR周界入侵AI算法检测方案

在城市管理和公共安全领域&#xff0c;安全视频监控的重要性日益凸显。AI视频智能分析平台基于深度学习和计算机视觉技术&#xff0c;利用AI入侵算法&#xff0c;能够实时、精准地监测周界入侵行为。 TSINGSEE青犀在视频监控及AI视频智能分析领域拥有深厚的技术积累和丰富的实…

2020年3月25日 Go生态洞察:Go、Go社区与疫情大流行

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

2024年最受欢迎的项目管理工具盘点

十大项目管理系统包括&#xff1a;1.产品研发项目管理工具&#xff1a;PingCode&#xff1b;2.通用项目协作工具&#xff1a;Worktile&#xff1b;3.开源项目管理系统&#xff1a;Redmine&#xff1b;4.IT/敏捷项目管理系统&#xff1a;Jira&#xff1b;5.免费个人项目管理&…

java基础进阶-线程池

1、线程池 线程池就是一个可以复用线程的技术。 2、应用场景 用户每发起一个请求&#xff0c;后台就需要创建一个新线程来处理&#xff0c;下次新任务来了肯定又要创建新线程处理的&#xff0c;而创建新线程的开销是很大的&#xff0c;并且请求过多时&#xff0c;肯定会产生大…

2023年【起重机械指挥】考试题库及起重机械指挥考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【起重机械指挥】考试题库及起重机械指挥考试资料&#xff0c;包含起重机械指挥考试题库答案和解析及起重机械指挥考试资料练习。安全生产模拟考试一点通结合国家起重机械指挥考试最新大纲及起重机械指挥考试真…

OpenSSL 使用AES对文件加解密

AES&#xff08;Advanced Encryption Standard&#xff09;是一种对称加密算法&#xff0c;它是目前广泛使用的加密算法之一。AES算法是由美国国家标准与技术研究院&#xff08;NIST&#xff09;于2001年发布的&#xff0c;它取代了原先的DES&#xff08;Data Encryption Stand…

设计师福利!2024在线图标设计网站推荐,不容错过的宝藏!

在当今竞争激烈的商业环境中&#xff0c;公司或个人品牌的视觉识别元素已经成为区分你和竞争对手的关键因素之一。一个独特而引人注目的标志可以深深扎根于人们的心中&#xff0c;并在消费者心中建立一个强烈的品牌印象。如果你正在寻找合适的工具来创建或改进你的标志&#xf…

Nginx系列-正向代理和反向代理

Nginx系列-正向代理和反向代理 文章目录 Nginx系列-正向代理和反向代理1. 三个对象2. 两种场景代理2.1. 正向代理2.2. 反向代理 3. 两种场景的对比3.1 为什么叫做反向代理3.2 正向代理和反向代理的作用 1. 三个对象 客户端&#xff1a;发出请求到代理&#xff0c;并接收代理的…

2019年11月20日 Go生态洞察:Go开发者调查启动

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

1128. 等价多米诺骨牌对的数量

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/number-of-equivalent-domino-pa…

主机的具体权限规划:ACL的使用

目的&#xff1a;针对某一用户或某一组来设置特定权限需求&#xff0c;针对上&#xff0c;接着设置 ACL可以针对单一用户&#xff0c;文件&#xff0c;或者目录来进行rwx的权限设置&#xff0c;对于需要特殊权限的设置非常有帮助。 第一&#xff0c;查看文件系统是否支持&…

frida - 2.hook使用

frida hook 方法 下面是frida客户端命令行的参数帮助 Frida两种操作模式 1.attach 模式 将一个脚本注入到 Android 目标进程,即需要App处于启动状态, 这意味着只能从 当前时机往后hook。 frida -U -l myhook.js com.xxx.xxxx参数解释: -U 指定对USB设备操作 -l 指定…