MySQL中的索引index(超详细)

news2025/1/16 20:09:41

概念:

在MySQL中,索引(index)是一种特殊的数据结构,它能够加快数据库中数据的检索速度。索引可以看做是一本书的目录,它提供了一种快速查找数据的方式。

MySQL中的索引是建立在一张表的一列或多列上的,用于加快对表中数据的查找速度。索引可以是单列索引,也可以是多列索引。当我们在一个表上创建了索引后,MySQL就会根据这个索引来建立一个索引文件,该文件中存储着每个值对应的行的物理位置。

MySQL支持多种类型的索引,例如B-tree索引、哈希索引、全文索引等。其中,B-tree索引是最常见和常用的索引类型,它可以在查询时进行快速的范围查找、排序和分组操作。

在数据库中使用索引可以大大提高数据的检索速度,但同时也会增加索引维护的开销,例如索引的创建、更新和删除操作。因此,索引的设计和使用需要根据具体的业务场景进行权衡和选择。

什么是索引?

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

    添加索引原则上来说可以大大的提高数据获取的效率。

索引的优势:

        提高数据检索的效率,降低数据库 的IO成本。

        通过索引列对数据进行排序,降低 数据排序的成本,降低CPU的消 耗。

索引的劣势:

        索引也是占用空间的。

        索引大大提高了查询效率,同时却也降低更新表的速度, 如对表进行INSERT、UPDATE、DELETE时,效率降低。

索引结构


 概述
        MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,索引都有B+Tree索引、Hash索引、R-tree(空间索 引) 、Full-text(全文 索引)。我们常用的为B+Tree和Hash索引。

 B+Tree
        B+Tree是B-Tree的变种,主要有以下三点区别:

  •          所有的数据都会出现在叶子节点。
  •          叶子节点形成一个单向链表。
  •          非叶子节点仅仅起到索引数据作用,具体的数据都是在叶子节点存放的。

        然而MySQL中又对B+Tree做了优化, 在原 B+Tree 的基础上,增加一个指向相邻叶子节点 的链表指针,就形成了带有顺序指针的 B+Tree ,提高区间访问的性能,利于排序。
Hash
        MySQL中除了支持B+Tree索引,还支持一种索引类型---Hash索引。

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

        如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可 以通过链表来解决,如果了解java的话应该很好理解。

Hash索引的优点:

        查询效率高,通常(不存在hash冲突的情况)只需要一次检索就可以了,效率通常要高于B+tree索引。

Hash索引的缺点:
        Hash 索引只能用于对等比较 (= , in) ,不支持范围查询( between , > , < , ... ) 。
        
         无法利用索引完成排序操作 。


 索引分类


索引分类
        在MySQL数据库,将索引的具体类型主要分为以下几类:主键索引、唯一索引、常规索引、全文索引。

聚集索引&二级索引
        而在在InnoDB存储引擎(MySQL默认存储引擎)中,根据索引的存储形式,又可以分为以下两种:

 聚集索引选取规则:
        如果存在主键,主键索引就是聚集索引。

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

        如果表没有主键,且没有合适唯一索引,InnoDB会自动生成一个rowid作为隐藏的聚集索引。

聚集索引&二级索引的区别:

        聚集索引的叶子节点下挂的是这一行的数据 。
        二级索引的叶子节点下挂的是该字段值对应的主键值。


 索引语法


创建索引:

        CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name ( index_col_name,... );

        演示:例如给user表的name字段添加索引,中括号里的参数是可以省略的。

        CREATE INDEX idx_user_name ON user(name);

 查看索引:

        SHOW INDEX FROM table_name ;

        演示:例如查看user表中的索引。

        SHOW INDEX FROM user ;


删除索引:

        DROP INDEX index_name ON table_name ;

        演示:例如删除我们刚刚创建的索引。

        DROP INDEX idx_user_name ON user ;

5 索引使用
        介绍索引的使用之前,我们先要了解一下explain这个函数

explain
        EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,包括在 SELECT 语句执行 过程中表如何连接和连接的顺序。

语法:

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

        EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件 ;

        例如:我要查询user表中id=1的数据,其中id为主键索引

        explain select * from tb_user where id = 1;

简单介绍一下比较重要的参数:

type:表示连接类型,性能由好到差的连接类型为NULL、system、const、 eq_ref、ref、range、 index、all 。在我们编写代码时,type尽量要往前靠。

possible_key: 显示可能应用在这张表上的索引,一个或多个。
key: 实际使用的索引,如果为 NULL ,则没有使用索引。
key_len: 表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下, 长度越短越好 。


最左前缀法则


        如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。

        以tb_user表为例,我们先看一下tb_user表创建的索引。

   在 tb_user 表中,有一个联合索引,这个联合索引涉及到三个字段,顺序分别为:profession, age,status。

在执行以下代码时:

  explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';

  可以看到在这里使用到了索引的,key_len为54。

   explain select * from tb_user where profession = '软件工程';

 可以看到满足最左前缀法则时是可以用到索引的,key_len=47;

explain select * from tb_user where profession = '软件工程' and status = '0';

可以看到status字段是不符合最左前缀法则的,跳过了联合索引中间的age字段,这时的key_len的 长度也为47。所以可以得出若不满足最最前缀法则实惠导致联合索引部分失效的情况。

范围查询


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

 explain select * from tb_user where profession = '软件工程' and age > 30 and status = '0';

     当范围查询使用> 或 < 时,走联合索引了,联合索引全走长度为54这里索引的长度为49,就说明范围查询右边的status字段是没有走索引的。

索引失效情况


 字符串不加引号


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

   explain select * from tb_user where profession = '软件工程' and age = 31 and status = 0;

如果字符串不加单引号,对于查询结果,没什么影响,但是数据库存在隐式类型转换,key_len长度为49,索引部分失效了。

 索引列运算


 若在索引列上进行运算操作, 索引则会失效。

explain select * from tb_user where substring(profession,1,2) = '软件' and age = 31 and status = 0;

 可以看到联合索引直接全部失效了,这里若是单例索引也会失效的。

 模糊查询

   如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。执行以下两句代码:

    explain select * from tb_user where profession like '软件%';

    explain select * from tb_user where profession like '%工程';

经过上述的测试,我们发现,在like模糊查询中,在关键字后面加%,索引可以生效。而如果在关键字 前面加了%,索引将会失效。

 or连接条件

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

  先看下tb_user表的索引情况。

explain select * from tb_user where id = 10 or age = 23;

 

可以看到id是主键索引,而age并没有索引,所以这里索引失效了。

 SQL提示

  SQL提示,是优化数据库的一个重要手段,简单来说,就是在 SQL 语句中加入一些人为的提示来达到优 化操作的目的。
        use index : 建议MySQL使用哪一个索引完成此次查询(仅仅是建议,mysql内部还会再次进 行评估)。

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

 ignore index : 忽略指定的索引。

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

 

 force index : 强制使用索引。

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

 

 覆盖索引

尽量使用覆盖索引,减少select *。 那么什么是覆盖索引呢? 覆盖索引是指 查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到 。

        也就是你要获取的数据就在叶子节点存放的键值以及主键id内。

索引前缀

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

语法: create index idx_xxxx on table_name(column(n)) ;

示例: 为tb_user表的email字段,建立长度为5的前缀索引。

create index idx_email_5 on tb_user(email(5));

  单例索引和联合索引 

  1.         单列索引:即一个索引只包含单个列。
  2.         联合索引:即一个索引包含了多个列。

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

索引设置原则

  1.  针对于数据量较大,且查询比较频繁的表建立索引。
  2.  针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立引。
  3.  尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  4.  如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  5.  尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间避免回表,提高查询效率。
  6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

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

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

相关文章

开发者社区项目开发流程

项目流程&#xff1a; 项目创建 首先创建一个文件夹&#xff0c;然后找到要创建项目的文件夹 输入CMD 进入小黑窗 输入“vue create 项目名” 创建我们这个项目(其中细节Ctrl左键点击链接见个人博客(99条消息) 创建Vue项目流程_啊唯11的博客-CSDN博客) 2.删除项认文件&#x…

C++命名空间域namespace与域作用限制符: :,cin,cout输入输出简单介绍

TIPS C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等C总计63个关键字&#xff0c;C语言32个关键字&#xff0c;具体没有必要先不去管它 域&#xff0c;命名空间域与namespace关键字 cpp需要解决的第一…

Java后端面试题 重难点和被问到没答上来的点(包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue等)

以下是我记录的一些重点问题和面试中被问到没答上来的问题&#xff0c;包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue 问题目录 1.fail-safe和fail-fast2.四引用3.explain字段重要内容4.maven三大生命周期5.MYSQL 创建修改表6.数据库三范式7.Strin…

华科超算用户手册的学习笔记

1. 资源计费 1.1 费用记账 日期费用&#xff08;上限3000元&#xff09;2023.04.171002023.04.18200总计300 1.2 创建实例时显示项目的余额不足 这是因为项目账户之中目前还没有足够的卡时&#xff1b; Note 这里是因为上次充值的卡时还在田老师的个人账户中&#xff0c;还需…

vue el-table 单机行选中高亮并获取行数据,再次单击取消行选中

1. 效果展示 当没有行被选中时&#xff0c;按钮是不可用的 当有行被选中时&#xff0c;该行高亮&#xff0c;同时按钮可用 再次点击该行&#xff0c;取消高亮&#xff0c;按钮不可用 2. 代码 2.1 组件代码 table设置了highlight-current-row&#xff0c;可以在选中某个数据行…

List集合和Set集合的区别

Collection集合总结 在进行Java开发的时候经常会用到集合&#xff0c;而集合又主要分为两种&#xff1a;Collection单列集合和Map集合。这里主要介绍一下Collection的一些常用子接口的区别。 Collection集合&#x1f62e; 指单列集合&#xff0c;存储的一组对象。 List&#x…

4大方法,教你如何做好项目管理

作为一个项目经理&#xff0c;项目管理是我们日常工作最核心的一项职能。无论是公司的业务开发还是重大项目的推进&#xff0c;都离不开项目管理。然而对于很多初入职场的人来说&#xff0c;项目管理还是一个相当新颖、陌生的领域&#xff0c;因此我今天就来分享一些我在项目管…

【安全与风险】密码安全和用户认证

密码安全和用户认证 基本问题证明你是谁为什么要验证还需要什么基于口令的身份认证常用使用模式常用使用模式可惜的是社会工程悉尼大学 (绿化96)尴尬和记忆关于密码使用的3个主要问题UNIX形式的密码密码散列字典式攻击影子密码其他密码问题生物计量学多模式生物识别系统定义为什…

数字化体验时代,企业如何做好内部知识数字化管理

随着数字化时代的到来&#xff0c;企业内部的知识管理也面临着新的挑战和机遇。数字化技术的应用&#xff0c;可以极大地提高企业内部知识的数字化管理效率和质量&#xff0c;从而提升企业内部的工作效率、员工满意度和企业竞争力。本文将从数字化时代的背景出发&#xff0c;探…

NVM安装nodejs的方法

前提&#xff1a; 为解决nodejs升级后出现的各种问题&#xff0c;使用NVM在一台电脑上安装多个版本的nodejs&#xff0c;以便项目可以根据自身使用的node版本来开发。 nodejs版本的查询地址&#xff1a; https://nodejs.org/zh-cn/download/releases/ nodejs下载官网地址&…

17.样式冲突

写在 .vue 组件中的样式会全局生效&#xff0c;比如我现在有一个LEFT组件 有一个RIGHT组件 将LEFT组件与RIGHT组件放在App组件中 发现我只给LEFT样式&#xff0c;但是在RIGHT中也生效了 为了避免这种情况&#xff0c;我们有下面几种解决方式 目录 1 具体到指定的标签 2 sc…

【微信小程序-原生开发】实用教程22 - 绘制图表(引入 echarts,含图表的懒加载-获取到数据后再渲染图表,多图表加载等技巧)

最终效果预览 实现流程 微信小程序中使用 echarts 需使用官方提供的 ec-canvas 组件 1. 下载 ec-canvas 组件 点击下方链接&#xff0c;下载 ec-canvas 组件 https://gitcode.net/mirrors/ecomfe/echarts-for-weixin/-/tree/master 将其中的 ec-canvas 文件夹拷贝到微信小程序…

数据结构考研版——用栈实现后缀表达式前缀表达式求值

用栈实现后缀表达式求值 int calsub(float opand1,char op,float opand2,float &result) {if(op){resultopand1opand2;}if(op-){resultopand1-opand2;}if(op*){resultopand1*opand2;}if(op/){//判断是否为0一般把它与我们宏定义的极小值值进行比较&#xff0c;接近于0则视…

把你的阿里巴巴图标库转成你自己的@ant-design/icons

背景 我们使用iconfont-阿里巴巴矢量图标库来管理自己的一套图标&#xff0c;并且基于它的js资源&#xff0c;封装了自己的icons图标组件。封装的方法是使用了antd提供的createFromIconfontCN方法 但随着图标库越来越大&#xff0c;JS资源文件也变得越来越大。在业务中&#x…

protobuf序列化原理、安装与应用

目录 protobuf序列化 protobuf的原理 protobuf 的安装 编译message文件 应用protobuf protobuf序列化 protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式&#xff0c;性能比json和xml真的强很多&#xff0c;毕竟google出品。 官网&#xff1a;https:…

C语言笔记 | 一元三次方程

文章目录 0x00 前言 0x01 问题分析 0x02 代码设计 0x03 完整代码 0x04 运行效果 0x05 参考文献 0x06 总结 0x00 前言 在 1545 年&#xff0c;意大利学者卡丹所写的《关于代数的大法》中&#xff0c;提出了一元三次方程的求根公式。人们将其称为卡丹公式。对于标准型的一…

Python 彩蛋 —— 开发人员留下的惊喜

Python 彩蛋 —— 开发人员留下的惊喜 简介&#xff1a;Python 核心程序开发人员在软件内部设计了2个彩蛋。一起来看看吧。 文章目录 Python 彩蛋 —— 开发人员留下的惊喜&#x1f4a1;彩蛋一&#xff1a;Python 之禅&#x1f4a1;彩蛋二&#xff1a;Python 有趣的漫画 &#…

程序员面试完之后,人麻了...

去面试吧 面不被录用的试 面hr为了完成任务的试 面一轮二轮没有下文试 面需要通勤2小时的试 面随时加班的试 ...... 今年的“金三银四”被网友们称为“铜三铁四”&#xff0c;招聘软件上的岗位都能背下来了&#xff0c;简历却依然石沉大海。 好不容易等来个回复&#xff…

南京邮电大学通达学院2023《电子装配实习》报告

南京邮电大学通达学院2023《电子装配实习》报告 一 声明二 题目/实习报告提示三 例答 红笺寄 休遣玉人知 ——赠nmy 一 声明 南京邮电大学通达学院2023《电子装配实习》报告 答案更新时间:2023.04.10&#xff0c;已更新完成&#xff0c;如无错误不在更新 由于作者解答能力有限…

计算带宽使用情况

由于大多数组织依靠其 IT 基础架构进行日常业务关键型运营&#xff0c;因此网络带宽可以对其网络性能产生巨大影响。连接不良可能会使组织花费大量资金并影响生产力。这就是为什么监控和计算带宽使用情况对于确保组织的最佳网络带宽性能至关重要的原因。 在计算企业的带宽使用…