慢查询引发对mysql索引的探索

目录

一、索引分类

1.1 聚簇索引结构

1.2 非聚簇索引(二级索引)

1.3 主键索引

1.4 唯一索引

1.5 普通索引

1.6 前缀索引

1.7 联合索引

1.8 索引下推

1.9 索引区分度

二、优化索引的方法

2.1 索引的特点

2.2 适合创建索引的情况

2.3 不适合创建索引的情况

2.4 优化索引的方法


慢查询的原因之一就是索引使用不当,本文对索引的本质和结构来剖析如何使用索引

一、索引分类

索引是数据的目录,是一种数据结构,为了快速检索与查找数据

索引分类:

维度类别
数据结构B+tree索引、Hash索引、Full-text索引
物理存储聚簇索引(主键索引)、二级索引(辅助索引)
字段特性主键索引、唯一索引、普通索引、前缀索引
字段个数单列索引、联合索引

MySQL 存储引擎默认是InnoDB,在InnoDB中必须有聚簇索引,这是由于InnoDB存储引擎的索引结构B+tree有关系。

在创建表时,会创建一个聚簇索引:

  • 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
  • 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key)
  • 如果上面两个都没有,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key)

1.1 聚簇索引结构

如图:B+树是一个多叉树,叶子节点存放数据,非叶子节点存放索引,每个节点都是按照主键顺序存放,叶子节点中的数据包括主键索引、数据、上一个节点的指针和下一个结点的指针

根据上面的图分析 select * from product where id=5

第一步:将id=5与根节点索引(1,10,20)比较,5在(1,10)之间,索引搜索找到第二层节点

第二步:将id=5与第二层节点(1,4,7)比较,5在(4,7)之间,找到第三层索引

第三步:在(4,5,6)之间查找,找到索引值=5的行数据

InnoDB的索引和数据都是存储在硬盘中的,每次读取数据都要进行一次硬盘IO操作,上述步骤一共进行了3个IO操作。

1.2 非聚簇索引(二级索引)

非聚簇索引,例如product值是二级索引,则用product创建的顺序索引结构如下:

其中非叶子节点是product索引值,而叶子节点放的是product索引值与主键数据

分析:select * from product where product = '0002'; 

第一步:在非聚簇索引中知道product=0002的主键索引值,id=2

第二步:回表查询,在聚簇索引中根据id=2查询行数据

回表:当查询使用非聚集索引(secondary index)时,需要先通过索引找到对应的数据行主键,然后再根据主键去聚集索引(primary index)中获取完整数据行的过程。

非回表查询:

select id from product where product = '0002'; 

查询的id就在非聚簇索引中,不需要回表去主键索引中查询,这种在二级索引中就可以查到结果的过程叫覆盖索引,查一个B+树就可以找到。

1.3 主键索引

建立在主键字段上,创建表的时候一起创建,一个表只有一个主键索引,主键索引列不能为空值

CREATE TABLE table_name{...PRIMARY KEY(id) USING BTREE
}

1.4 唯一索引

与主键索引不同的地方,一个表可以有多个唯一索引,唯一索引允许索引列有空值,但是唯一索引列的值必须唯一。

//创建表时创建索引
CREATE TABLE table_name(...UNIQUE KEY(column1,column2)
);//建表后增加索引
CREATE UNIQUE INDEX index_name 
ON table_name(column1,column2)或者
ALTER TABLE table_name 
ADD UNIQUE (column1, column2);

1.5 普通索引

建立在普通的字段上,不要求字段值非空,也不要求字段值唯一

//创建表时创建索引
CREATE TABLE table_name(...INDEX(column1,column2)
);//建表后增加索引
CREATE INDEX index_name 
ON table_name(column1,column2)或者
ALTER TABLE table_name 
ADD INDEX (column1, column2);

1.6 前缀索引

对字符类型字段的前几个字符创建索引,目的是为了节省索引所占的存储空间,提高查询效率

1.7 联合索引

由多个字段组成的索引为联合索引,例如productId和productName两个字段创建的索引,其索引结构如下:

联合索引的非叶子节点是用productId和name做值,索引先按照productId排序,productId相同时按照name排序,所以联合索引需要满足最左匹配原则,如果不满足,则该联合索引就会失效,无法利用索引提高查询效率。

如果语句where name=ipad8,则无法使用联合索引(productId,name),因为name字段是局部有序,全局无序的,利用索引的前提是索引是全局有序的。

举例说明,哪些情况联合索引生效,联合索引(a,b)

语句索引说明
select * from table where a>1 and b=2a字段用到了联合索引,b字段没有用到a字段是有序的,可以定位到符合a>1的纪录,但是b是无序的
select * from table where a>=1 and b=2a,b字段都用到了联合索引a>=1索引可以很快定位到a=1的纪录,b=2可以将索引定位到a=1,b=2的纪录,然后往后扫描
select * from table where a between 2 and 8 and b=2a,b字段都用到了联合索引between and相当于a>=2 and a<=8,b=2可以进一步缩小索引扫描的行数
select * from table where a like 'j%' and b=2a,b字段都用到了联合索引当索引a字段值为‘j%’时,b=2可以减少扫描的二级索引纪录行数

1.8 索引下推

select * from table where a>1 and b=2,对于联合索引(a,b),只有a字段用到了索引,那b字段是回表查询后进行判断呢还是在二级索引中判断呢?

mysql5.6后,引入了索引下推,可以在二级索引中之间判断其它字段是否满足条件,减少回表的次数,例如在二级索引中查询出a>2的纪录之后,会在二级索引中包含的字段b进行判断是否满足b=2

1.9 索引区分度

建立联合索引时,需要将区分度大的字段排在前面,区分度小的排在后面,区分度越大过滤的数据越多,区分度=一个字段值去重后的个数/该字段总数

二、优化索引的方法

2.1 索引的特点

优点:提高查询效率

缺点:占用物理空间,数量越大占用越多;创建和维护索引占用时间,索引越大占用时间越多;增加表增删改的效率,因为每次更新都要动态维护索引数据。

2.2 适合创建索引的情况

  1. 字段有唯一性限制;
  2. where中的字段,如果查询条件是多个字段,可以创建联合索引;
  3. group by与order by中的字段,因为索引是排好序的,不需要重新排序;

2.3 不适合创建索引的情况

  1. 字段区分度低的,例如性别,优化器会在区分度很低时,放弃索引,采用全表扫描;
  2. where 、group by、order by中用不到的字段,索引的作用是快速定位,否则只会占用空间;
  3. 经常更新的字段不适合创建索引,会增加维护索引的成本;
  4. 数据量很少时不适合创建索引,数据量很少时全表扫描会更快;

2.4 优化索引的方法

  1. 前缀索引优化:大字符做索引时,用前缀索引,减少索引字段大小,提高索引页中存储的索引数量
  2. 覆盖索引优化:对于查询的字段可以创建联合索引,直接在二级索引中查询出所有的数据,不需要回表查询主键索引,减少IO操作
  3. 主键索引自增:自增索引在增加数据时,直接开辟新的页存储数据,不需要移动其他的数据,否则会导致页分裂,造成内存碎片,索引结构不紧凑,影响查询效率。
  4. 防止索引失效:
  • 不符合最左匹配原则:例如like '%xx'或者like '%xx%'
  • 对索引列进行计算、函数、类型转换
  • OR条件,只有一个条件有索引时,也会索引失效

参考:索引常见面试题 | 小林coding

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

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

相关文章

启用不安全的HTTP方法

背景&#xff1a; 今天被安全检测出一个这样的问题&#xff1a;启用不安全的HTTP方法。DELETE方法是用来调试web服务器连接的http方式&#xff0c;支持该方式的服务器文件可能被非法删除&#xff1b;PUT方法用来向服务器提交文件&#xff1b;TRACE方法本用于客户端测试到服务器…

fvcom 水深文件dep制作

fvcom 水深文件dep制作 fvcom 水深文件dep制作20250630 本次案例网格和水深展示 vv image Figure 1 Model domain 本次制作其它驱动文件的输入文件为yellowsea.2dm 格式2dm; 文件内容格式详细介绍参考&#xff1a; https://www.xmswiki.com/wiki/SMS:2D_Mesh_Files_*.2dm …

ViewModel是EventFlow-State映射

ViewModel负责组装界面状态State。引发State变换的原因有很多&#xff0c;比如用户点击某个按钮&#xff0c;一次网络请求受到应答&#xff0c;一次本地数据库查询返回结果等等。因此ViewModel是根据各种事件生成State的对象&#xff0c;换句话说&#xff0c;是一个从多个事件流…

javaweb Day2

PreparedStatement作用: 预编译SQL语句并执行: 预防SQL注入问题 SQL注入:SQL注入是通过操作输入来修改事先定义好的SQL语句&#xff0c;用以达到执行代码对服务器进行攻击的方法。

Java项目:基于SSM框架实现的中学教学管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告】

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本景海中学教学管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据…

JVM调优实战 Day 15:云原生环境下的JVM配置

【JVM调优实战 Day 15】云原生环境下的JVM配置 文章标签 jvm调优, 云原生, Java性能优化, JVM参数配置, 容器化部署, Kubernetes, Docker, JVM在云原生中的应用 文章简述 随着云原生技术的普及&#xff0c;Java 应用越来越多地运行在容器&#xff08;如 Docker&#xff09;和…

数据结构day7——文件IO

一、标准 IO 的起源与概念 标准 IO&#xff08;Standard Input/Output&#xff09;是由 Dennis Ritchie 在 1975 年设计的一套 IO 库&#xff0c;后来成为 C 语言的标准组成部分&#xff0c;并被 ANSI C 所采纳。它是对底层文件 IO 的封装&#xff0c;提供了更便捷、可移植的文…

6.Docker部署ES+kibana

部署ES&#xff08;Elasticsearch&#xff09;kibana 1.ES暴露的端口很多 2.ES十分消耗内存 3.ES的数据一般需要挂载出去&#xff0c;放在安全目录&#xff08;挂载) elastic 前往官方手册 1.下载运行elasticsearch的 docker run -d --name elasticsearch --net somenet…

使用mysqldump对mysql数据库进行备份

目录 1软件说明 2语法格式 3备份流程 3.1只备份指定数据库中表和数据 3.1.1准备目录 3.1.2备份db1数据库里面的所有表信息 3.1.3还原备份 3.2备份数据库结构 3.2.1备份db1数据库的结构和数据 3.2.2还原数据库 3.3备份所有数据库 3.3.1备份数据库 3.3.2还原数据库 1…

vue3路由跳转打开新页面

Vue3 路由跳转打开新页面的方法 在 Vue3 中&#xff0c;有几种方法可以实现路由跳转时打开新页面&#xff1a; 1. 使用 router.resolve 方法 import { useRouter } from vue-routerconst router useRouter()const openNewPage (path) > {const resolved router.resolv…

SeaTunnel 社区 2 项目中选“开源之夏 2025”,探索高阶数据集成能力!

Apache SeaTunnel 社区在“开源之夏 2025”中再传捷报&#xff0c;共有两个项目成功入选&#xff0c;聚焦于 Flink CDC schema 支持与元数据管理的生态扩展方向&#xff0c;体现出 SeaTunnel 在实时数据集成和平台化能力构建上的深入布局。 中选项目与学生如下&#xff1a; 《…

Neo4j无法建立到 localhost:7474 服务器的连接出现404错误

一、确认中文路径问题&#xff08;核心原因&#xff09; 安装路径包含中文&#xff0c;可能导致 Windows 命令行或 Neo4j 解析路径时出错。 解决方法&#xff1a; 重新安装 Neo4j 到英文路径&#xff08;推荐&#xff09;&#xff1a; 将 Neo4j 解压或安装到不含中文的目录&a…

锂离子电池均衡拓扑综述

锂离子电池均衡拓扑综述 一、引言 锂离子电池因其高能量密度、长循环寿命等优点&#xff0c;在电动汽车、储能系统等领域得到了广泛应用。然而&#xff0c;电池组在使用过程中&#xff0c;由于电池个体差异、充放电管理等因素&#xff0c;会出现荷电状态&#xff08;SOC&…

[面试] 手写题-浅拷贝,深拷贝

浅拷贝 // 浅拷贝 function shallow(obj) {const newObj {}for (const key in obj) {// 保证 key 不是原型的属性if (obj.hasOwnProperty(key)) {newObj[key] obj[key]}}return newObj }深拷贝 递归 O(n^2) // 深拷贝 function deepClone(obj {}) {// 如果传入的是 null&am…

BehaviorTree.ROS2安装记录

坑比库&#xff0c; 首先 git clone https://github.com/BehaviorTree/BehaviorTree.ROS2.git 依赖 git clone https://github.com/PickNikRobotics/cpp_polyfills.git git clone https://github.com/PickNikRobotics/RSL.git git clone https://github.com/PickNikRobotics/…

Vue基础(19)_Vue内置指令

我们学过的vue内置指令&#xff1a; v-bind&#xff1a;单向绑定解析表达式&#xff0c;可简写为&#xff1a;:xxx v-model&#xff1a;双向数据绑定 v-for&#xff1a;遍历数组/对象/字符串 v-on&#xff1a;绑定事件监听&#xff0c;可简写为 v-if&#xff1a;条件渲染(动态控…

排列组合初步

什么是排列组合 排列组合是计数问题&#xff0c;顺序不同且值相同算两种方案是排列&#xff0c;顺序不同且值相同算一种方案是组合。 暴力枚举方案能算出方案数&#xff0c;太耗时&#xff0c;运用加法原理和乘法原理可降低时间复杂度。先将原问题拆解成子问题&#xff0c;根…

SQL调优方案对比与最佳实践

问题背景介绍 在大型互联网或企业级应用中&#xff0c;数据库往往成为系统性能的瓶颈。随着数据量和并发量的增长&#xff0c;单一的 SQL 查询可能出现响应迟缓、锁等待、全表扫描等性能问题。为保证系统的稳定性和用户体验&#xff0c;需要对 SQL 查询做深入的调优。常见的调…

Terraform Helm:微服务基础设施即代码

&#x1f680; Terraform & Helm&#xff1a;微服务基础设施即代码 &#x1f4da; 目录 &#x1f680; Terraform & Helm&#xff1a;微服务基础设施即代码1. 引言 &#x1f680;2. 环境与依赖 &#x1f9f0;3. 架构示意 &#x1f3d7;️4. Terraform 定义云资源 &…

清理 Docker 缓存占用

Docker 缓存主要包括未使用的镜像、容器、卷和网络等资源。清理缓存可以提高磁盘空间&#xff0c;线上升级次数比较多的话&#xff0c;服务器中Docker缓存会非常严重&#xff0c;做下清理瘦身会有意想不到的效果 清理未使用的镜像 运行以下命令删除未被任何容器引用的镜像&…