MySQL索引优化实战一

#插入一些示例数据
 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.mfbz.cn/a/197495.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Oracle(2-7)Instance and Media Recovery Structures

文章目录 一、基础知识1、体系结构详解2、Database Files 数据库文件3、Database Other Files 其他数据文件4、Dynamic Views 动态视图5、Large Pool6、DB Buffer Cache,DBWn7、Configuring Tablespaces 配置表空间8、Redo Log Buffer, LGWR 二、基础操作1、查看数据库动态视图…

【开源】基于Vue.js的高校学生管理系统的设计和实现

项目编号&#xff1a; S 029 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S029&#xff0c;文末获取源码。} 项目编号&#xff1a;S029&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生管理模块2.2 学院课程模块2.3 学…

【微服务专题】微服务架构演进

目录 前言阅读对象阅读导航前置知识笔记正文一、系统架构的演变1.1 单体架构1.2 单体水平架构1.3 垂直架构1.4 SOA架构1.5 微服务架构 二、如何实现微服务架构2.1 微服务架构下的技术挑战2.2 微服务技术栈选型2.3 什么是Spring Cloud全家桶2.4 Spring Cloud Alibaba版本选择 学…

合并区间[中等]

一、题目 以数组intervals表示若干个区间的集合&#xff0c;其中单个区间为intervals[i] [starti, endi]。请你合并所有重叠的区间&#xff0c;并返回一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间。 示例 1&#xff1a; 输入&#xff1a;intervals […

人工智能-产生式系统实验(动物识别)

1.实验目的 1.熟悉知识的表示方法 2.掌握产生式系统的运行机制 3.产生式系统推理的基本方法。 2.实验内容 运用所学知识&#xff0c;设计并编程实现一个小型动物识别系统&#xff0c;能识别虎、金钱豹、斑马、长颈鹿、鸵鸟、企鹅、信天翁等七种动物的产生式系统。 规则库&…

SPSS生存分析:寿命表分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

智能优化算法应用:基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

分布式运用之ELK企业级日志分析系统

1.1 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 ElasticSearch&#xff1a; 是基于Lucene&#xff08;一个全文检索引…

Python(八十九)函数的参数的内存分析

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

SQL注入-数据库基础/SQL语法

目录 一&#xff0c;数据库概述 1.1 数据库 1.2 了解 ACID 理论 1.3 识别数据库 二&#xff0c;SQL 语法基础 三&#xff0c;SQL语句实例 3.1 SQL基础语句 3.2 SQL高级语句 四&#xff0c;基于SQL注入理解语法/函数 4.1 语法 4.2 函数 五&#xff0c;目录数据库info…

【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)

​ 目录 一、排序的概念及其运用1.1 排序的概念1.2 排序的应用1.3 常见的排序算法 二、常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序2.1.3 直接插入排序和希尔排序的性能对比 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序2.2.3 直接选择排序和堆排序的性能…

整车测试中的UDS诊断

UDS&#xff08;Unified Diagnostic Services&#xff0c;统一的诊断服务&#xff09;诊断协议是在汽车电子ECU环境下的一种诊断通信协议。这种通信协议被用在几乎所有由OEM一级供应商所制造的新ECU上面。这些ECU控制车辆的各种功能&#xff0c;包括电控燃油喷射系统&#xff0…

WPF中DataGrid解析

效果如图&#xff1a; 代码如下&#xff1a; <DataGrid Grid.Row"1" x:Name"dataGrid" ItemsSource"{Binding DataList}" AutoGenerateColumns"False"SelectedItem"{Binding SelectedItem,UpdateSourceTriggerPropertyChange…

Redis 主库挂了,如何不间断服务?

目录 1、哨兵机制的基本流程 2、主观下线和客观下线 3、如何选定新的主库&#xff1f; 总结 // 你只管前行&#xff0c;剩下的交给时间 在 reids 主从库集群模式下&#xff0c;如果从库发生故障了&#xff0c;客户端可以继续向主库或其他从库发送请求&#xff0c;进行相关的…

Spring Cloud,注册中心,配置中心,原理详解

文章目录 Spring Cloud&#xff0c;注册中心&#xff0c;配置中心&#xff0c;原理详解谈谈我个人对 spring Cloud 的理解 注册中心Eureka&#xff1a;服务搭建小结 Ribbo - 负载均衡1. 负载均衡流程2. 负载均衡策略 nacos注册中心1. 配置集群1. 创建 namespace2. 配置命名空间…

Redis 的过期策略都有哪些?

思考:假如redis的key过期之后&#xff0c;会立即删除吗&#xff1f; Redis对数据设置数据的有效时间&#xff0c;数据过期以后&#xff0c;就需要将数据从内存中删除掉。可以按照不同的规则进行删除&#xff0c;这种删除规则就被称之为数据的删除策略&#xff08;数据过期策略…

如何运行C/C++程序

一、在线运行C/C 码曰 - 让代码在云端多飞一会&#xff1a;这是一个支持C/C&#xff0c;Java&#xff0c;Python等多种语言的在线编程&#xff0c;编译运行&#xff0c;粘贴分享的平台。你可以在这里输入你的代码&#xff0c;点击运行按钮&#xff0c;就可以看到输出结果。你也…

【shell】多行重定向与免交互expect与ssh、scp的结合使用

目录 一、多行重定向 举例1&#xff1a;使用read命令接收用户的输入值会有交互过程 举例2&#xff1a;设置变量的值 举例3&#xff1a;创建用户密码 举例4&#xff1a;使用多行重定向写入文件中&#xff08;以repo文件举例&#xff09; 举例5&#xff1a;变量设定 二、免…

微信小程序开发——开发账号注册与配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 概述 本文的重点在于介绍注册微信小程序开发账号的步骤及其流程。 账号注册 请点击官方网站右上角的 https://mp.weixin.qq.com/ 立即注册&#xff0c;图示如下&#xf…

【C++ Primer Plus学习记录】while循环

while循环是没有初始化和更新部分的for循环&#xff0c;它只有测试条件和循环体&#xff1a; while(test-condition)dody 首先&#xff0c;程序计算圆括号内的测试条件表达式。如果该表达式为true&#xff0c;则执行循环体内的语句。与for循环一样&#xff0c;循环体也由一条…
最新文章