MySQL- 索引

news2025/1/19 23:14:13

索引是帮助MySQL高效获取数据的数据结构(有序)。在数据之外, 数据库系统还维护着满足特定查找算法的数据结构, 这些数据结构以某种方式引用数据, 这样就可以在这些数据结构上实现高级查找算法, 这种数据结构就是索引。

索引结构

MySQL的索引是在存储层实现的, 不同的存储引擎有不同的结构

 

索引结构

描述

B+Tree索引

最常见的索引类型,大部分引擎都支持 B+ 树索引

Hash索引

底层数据结构是用哈希表实现的, 只有精确匹配索引列的查询才有效, 不 支持范围查询

R-tree(空间索 引)

空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类 型,通常使用较少

Full-text(全文 索引)

是一种通过建立倒排索引,快速匹配文档的方式。类似于 Lucene,Solr,ES

二叉树

如果主键是顺序插入的,则会形成一个单向链表

缺点: 顺序插入时, 会形成一个链表, 查询性能大大降低。大数据量情况下, 层级较深, 检索速度慢。

可以选择红黑树,红黑树是一颗自平衡二叉树,那这样即使是顺序插入数 据,最终形成的数据结构也是一颗平衡的二叉树

红黑树: 大数据量情况下, 层级较深, 检索速度慢。

在MySQL的索引结构中,并没有选择二叉树或者红黑树,而选择的是B+Tree

 

B-Tree (多路平衡查找树)

B-Tree,B树是一种多路平衡查找树,相对于二叉树,B树每个节点可以有多个分支,即多叉。 以一颗最大度数(max-degree)为5(5阶)的b-tree为例,那这个B树每个节点最多存储4个key,5个指针

特点:

5阶的B树,每一个节点最多存储4个key,对应5个指针。

一旦节点存储的key数量到达5,就会裂变,中间元素向上分裂。

在B树中,非叶子节点和叶子节点都会存放数据

数据结构动态变化的过程参考网站: B-Tree Visualization

B+Tree

B+Tree是B-Tree的变种

相对于B-Tree区别

所有的数据都会出现在叶子节点

叶子节点形成一个单向链表

非叶子节点仅仅起到索引数据作用,具体的数据都是在叶子节点存放的

MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上, 增加了一个指向相邻叶子节点的链表指针, 就形成了带有顺序指针的B+Tree, 提高区间访问的性能。

Hash

哈希索引就是采用一定的hash算法, 将键值换算成新的hash值, 映射到对应的槽位上, 然后存储在hash表中。

如果多个键值, 映射到一个相同的槽位上, 他们就产生了hash冲突, 可以通过链表来解决

索引特点

  1. Hash索引只能用于对等比较(=, in), 不支持范围查询(between, >, <, …)
  2. 无法利用索引完成排序操作
  3. 查询效率高, 通常只需要一次检索就可以, 效率通常高于B+tree索引

存储引擎支持

在MySQL中, 支持hash索引的是Memory引擎, 而InnoDB中具有自适应hash功能, hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

为什么InnoDB存储引擎选择使用B+tree索引结构?

相对于二叉树, 层级更少, 搜索效率更高

相对于B-tree, 无论是叶子节点还是非叶子节点, 都会保存数据, 这样导致一页中存储的键值减少, 指针跟着减少, 要同样保存大量数据, 只能增加树的高度, 导致性能降低

相对Hash索引, B+tree支持范围匹配及排序操作

索引分类

在MySQL数据库,将索引的具体类型主要分为以下几类

分类 

含义

特点

关键字

主键 索引

针对于表中主键创建的索引

默认自动创建, 只能 有一个

PRIMARY

唯一 索引

避免同一个表中某数据列中的值重复

可以有多个

UNIQUE

常规 索引

快速定位特定数据

可以有多个

全文 索引

全文索引查找的是文本中的关键词,而不是比
较索引中的值

可以有多个

FULLTEXT

聚集索引 & 二级索引

而在在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种

分类 

含义

特点

聚集索引(Clustered Index)

将数据存储与索引放到了一块,索引结构的叶子
节点保存了行数据

必须有,而且只 有一个

二级索引(Secondary Index)

将数据与索引分开存储,索引结构的叶子节点关
联的是对应的主键

可以存在多个

 

聚集索引选取规则

如果存在主键,主键索引就是聚集索引。

如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。

如果表没有主键,或没有合适的唯一索引,则InnoDB

会自动生成一个rowid作为隐藏的聚集索引

 

聚集索引和二级索引的具体结构如下

 

 

聚集索引的叶子节点下挂的是这一行的数据

二级索引的叶子节点下挂的是该字段值对应的主键值 

 

回表查询: 这种先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取 数据的方式,就称之为回表查询

 

索引语法

创建索引

Create [unique|fulltext] index index_name on table_name(index_col_name,…)

查看索引

Show index from table_name;

删除索引

Drop index index_name on table_name;

SQL性能分析

SQL执行频率

MySQL客户端连接成功后, 通过show [session|global] status命令可以提供服务器状态信息。通过如下命令, 可以查看当前数据库的insert, update, delete, select的访问频次

Show global status like 'Com_____';

Com_delete: 删除次数 

Com_insert: 插入次数

Com_select: 查询次数

Com_update: 更新次数

慢查询日志

慢查询日志记录了所有执行时间超过指定参数(long_query_time, 单位: 秒, 默认10秒)的所有SQL语句的日志

MySQL的慢查询日志默认没有开启, 需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

Show variables like 'slow_query_log';

# 开启MySQL慢日志查询开关

Show_query_log=1

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

Long_query_time=2

配置完毕之后, 通过以下指令重新启动MySQL服务器进行测试, 查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log

profile详情

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

profile操作:

Select @@have_profiling;

默认profiling是关闭的, 可以通过set语句在session/global级别开启profiling:

Set profiling=1;

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

# 查看每一条SQL的耗时基本情况

Show profiles;

# 查看指定query_id的SQL语句各个阶段的耗时情况

Show profile for query query_id;

# 查看指定query_id的SQL语句CPU的使用情况

Show profile cpu for query query_id;

Explain

Explain或者desc命令获取MySQL如何执行select语句的信息, 包括在select语句执行过程中表如何连接和连接的顺序

语法:

# 直接在select语句之前加上关键字explain/desc

Explain select 字段列表 from 表名 where 条件;

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 的值越大越好。

索引使用

最左前缀法则

如果索引了多列(联合索引), 要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始, 并且不跳过索引的列。

如果跳跃某一列, 索引将部分失效(后面的字段索引失效)。

范围查询

联合索引中, 出现范围查询(>, <), 范围查询右侧的列索引失效

索引失效情况

索引列运算

不要在索引列上进行运算操作, 索引将失效。

字符串不加引号

字符串类型字段使用时, 不加引号, 索引将失效。

模糊查询

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

or连接的条件

用or分割开的条件, 如果or前的条件中的列有索引, 而后面的列中没有索引, 那么涉及的索引都不会被用到。

数据分布影响

如果MySQL评估使用索引比全表更慢, 则不使用索引。

SQL提示

SQL提示, 是优化数据库的一个重要手段, 简单来说, 就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

use index:

Explain select * from tb_user index(idx_user_pro) where profession='软件工程'

Ignore index:

Explain select * from tb_user ignore(idx_user_pro) where profession='软件工程'

Force index:

Explain select * from tb_user force(idx_user_pro) where profession='软件工程'

覆盖索引

尽量使用覆盖索引(查询使用了索引, 并且需要返回的列, 在该索引中已经全部能够找到), 减少select *

Using index condition: 查找使用了索引, 但是需要回表查询数据

Using where;using index: 查找使用了索引, 但是需要的数据在索引列中能找到, 所以不需要回表查询数据

Extra

含义

Using where; Using
Index

查找使用了索引,但是需要的数据都在索引列中能找到,所以不需
要回表查询数据

Using index
condition

查找使用了索引,但是需要回表查询数据

前缀索引

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

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

前缀长度

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

Select count(distinct email)/count(*) from tb_user;

单列索引与联合索引

单列索引: 一个索引只包含了单个列

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

在业务场景中, 如果存在多个查询条件, 考虑针对查询字段建立索引时, 建议建立联合索引, 而非单列索引。

索引设计原则

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

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

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

4).  如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。

5).  尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间, 避免回表,提高查询效率。

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

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

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

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

相关文章

网友总结:面试超过一个小时,通过概率更低;面试时长在半小时以内,通过概率更高!...

面试时长跟通过概率有关系吗&#xff1f; 一位网友分享了自己的求职感想&#xff1a; 面试过程越长&#xff0c;差不多一个小时或者超过一个小时&#xff0c;问得越详细&#xff0c;通过的可能性越低。因为问得越细&#xff0c;说明这个公司越挑&#xff0c;需要候选人匹配度越…

【C++ 入坑指南】(05)数据类型

文章目录 一、整型sizeof 关键字 二、实型&#xff08;浮点型&#xff09;三、字符型四、字符串型4.1 C 风格字符串4.2 C 引入的 string 类类型 五、布尔类型&#xff08;bool&#xff09;六、类型转换6.1 静态转换&#xff08;Static Cast&#xff09;6.2 动态转换&#xff08…

软考A计划-真题-分类精讲汇总-第六章(软件工程)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

阿里云服务器安装宝塔Linux面板教程图解

使用阿里云服务器安装宝塔面板教程&#xff0c;阿里云服务器网以CentOS操作系统为例&#xff0c;安装宝塔Linux面板&#xff0c;先远程连接到云服务器&#xff0c;然后执行宝塔面板安装命令&#xff0c;系统会自动安装宝塔面板&#xff0c;安装完成后会返回面板地址、账号和密码…

【mongoDB】mongodb权限验证 || mongodb重启 || mongodb常用命令

mongodb版本号 6.0 前言 mongoDB刚开始无需密码登录mongoDB有3默认数据库&#xff0c;分别为&#xff1a; admin 超级用户&#xff0c;能对所有数据库操作&#xff0c;执行管理员命令config 分片集群配置的数据库local 分片集群锁信息的集合test 这个数据库一般是隐式创建的&…

新书出版了(文末送书)

大家好&#xff0c;我是麦哥。 最近一位好友的新书出版了&#xff0c;由衷的替他开心&#xff0c;赶紧来支持一波。 新书长这样 这本书的作者是前中兴高级工程师&#xff0c;某知名培训机构的教学总监&#xff0c;现于某研究所担任重要的研发工作&#xff0c;我喜欢叫他彭老师。…

路径规划算法:基于蚁狮优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于蚁狮优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蚁狮优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法蚁狮…

路径规划算法:基于蝗虫优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于蝗虫优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蝗虫优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法蝗虫…

Python爬虫之美丽的汤——BeautifulSoup

本文概要 本篇文章主要介绍利用Python爬虫之美丽的汤——BeautifulSoup&#xff0c;适合练习爬虫基础同学&#xff0c;文中描述和代码示例很详细&#xff0c;干货满满&#xff0c;感兴趣的小伙伴快来一起学习吧&#xff01; 是不是以为今天要教大家怎么做饭&#xff1f;确实&…

MATLAB图像处理:图像分割、特征提取和目标识别的应用和优化

MATLAB图像处理&#xff1a;图像分割、特征提取和目标识别的应用和优化 作为一种常用的图像处理工具&#xff0c;MATLAB在图像分割、特征提取和目标识别等方面具有广泛的应用。本文将详细介绍这三个方面的应用和优化。 第一章&#xff1a;图像分割 图像分割是将一幅图像划分成…

阿里云服务器安装宝塔面板教程图解(超详细)

使用阿里云服务器安装宝塔面板教程&#xff0c;阿里云服务器网以CentOS操作系统为例&#xff0c;安装宝塔Linux面板&#xff0c;先远程连接到云服务器&#xff0c;然后执行宝塔面板安装命令&#xff0c;系统会自动安装宝塔面板&#xff0c;安装完成后会返回面板地址、账号和密码…

Django如何把SQLite数据库转换为Mysql数据库

大部分新手刚学Django开发的时候默认用的都是SQLite数据库&#xff0c;上线部署的时候&#xff0c;大多用的却是Mysql。那么我们应该如何把数据库从SQLite迁移转换成Mysql呢&#xff1f; 之前我们默认使用的是SQLite数据库&#xff0c;我们开发完成之后&#xff0c;里面有许多数…

『python爬虫』20. 用协程爬取一本小说(保姆级图文)

目录 1. 分析目标网站1.1 寻找所有章节信息1.2 寻找章节内容 2. 爬虫思路获取得到的信息首先要同步协程获取所有章节标题和cid写入异步任务然后根据章节标题和cid获取章节内容 3. 完整实现代码总结 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『python爬虫』…

linux命令文本命令之~~~ sort ~~ tr ~~cut ~~ uniq ~~split~~~paste~~eval

目录 一. sort命令二. uniq 命令三. tr命令四. cut命令五 . split六. paste 合并文件内容的列七. eval命令 一. sort命令 以行为单位对文件内容进行排序&#xff0c;也将他根据不同的数据类型来排序 比较原则是从首字符向后&#xff0c;依次按ASCII码进行比较&#xff0c;最后…

龟兔赛跑,环形链表解题思路:用兔子的速度,龟的智慧,和链表的结构,解决力扣难题

本篇博客会讲解力扣“141. 环形链表”的解题思路&#xff0c;这是题目链接。 审题 先来审题&#xff1a; 以下是输出示例&#xff1a; 以下是提示&#xff1a; 以下是进阶&#xff1a; 思路 本题有一种非常巧妙的解法&#xff1a;快慢指针法&#xff0c;又称龟兔赛跑法…

SpringBoot——默认页面在哪里?

简单介绍&#xff1a; 在之前我们创建了一个SpringBoot的应用程序&#xff0c;并且我们也启动了&#xff0c;但是我们都是在postman或者是在控制台看到了我们的界面&#xff0c;那么在浏览器中看到的界面其实只有一个&#xff1a; 这个界面其实就是SpringBoot的报错默认界面&a…

buuctf8

目录 crypto 摩丝 password 变异凯撒 Quoted-printable Rabbit web [护网杯 2018]easy_tornado [HCTF 2018]admin misc 被劫持的神秘礼物​编辑 crypto 摩丝 下载文件&#xff0c;得到一串摩斯密码 在线解码 password 下载文件 张三英文zs&#xff0c;加上生日&a…

opencv_contrib模块编译与安装

前言 由于opencv_contrib模块的安装依赖于opencv基础模块&#xff0c;所以看该教程前请先看一遍OpenCV基础模块安装教程 下载 下载 opencv_contrib模块&#xff08;需要与opencv基础模块版本号4.6.0相同&#xff0c;国内可以在gitcode下载&#xff09; 配置、编译、安装 打…

网工视角看基础网络,原来这么与众不同

大家好&#xff0c;我是老杨。 前两天去华为生态大会刚回来&#xff0c;颇为感慨。 感慨万物互联的世界越来越大&#xff0c;网络渗透度也越来越极致化。 网络很大&#xff0c;非常大&#xff0c;但在网工眼里&#xff0c;网络复杂又美妙&#xff0c;有着外行人难以理解的魅…

大数据Doris(十九):Doris索引介绍与前缀索引

文章目录 Doris索引介绍与前缀索引 一、Doris索引介绍 二、前缀索引 Doris索引介绍与前缀索引 一、Doris索引介绍 索引用于帮助快速过滤或查找数据。目前 Doris 主要支持两类索引: 内建的智能索引,包括前缀索引和 ZoneMap