MySQL:索引

MySQL官方对索引的定义为: 索引 (Index) 是帮助MySQL高效获取数据的数据结构。

提取句子主干,就可以得到索引的本质:索引是数据结构。

1. 什么是索引,索引的作用


索引是一种用于快速查询和检索数据的数据结构,帮助mysql提高查询效率的数据结构,而且是排好序的数据结构,存储在磁盘文件里。

索引的作用是在不读取整个表的情况下,使得数据库应用程序可以更快地查找数据,用户无法看到索引,只能被用来加速检索或查询。

优点:

  • 使用索引可以大大加快数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因。
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

缺点:

  • 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
  • 索引需要使用物理文件存储,也会耗费一定空间。

但是,使用索引一定能提高查询性能吗?

大多数情况下,索引查询都是比全表扫描要快的。但是如果数据库的数据量不大,那么使用索引也不一定能够带来很大提升。

索引建立的原则:

  • 在最频繁使用的、用以缩小查询范围的字段上建立索引。
  • 在最频繁使用的、需要排序的字段上建立索引。
  • 对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引。

2. 索引的类型

1. 主键索引(Primary Key)

数据表的主键列使用的就是主键索引。(唯一标识,主键不可重复,只能有一个列作为主键

一张数据表有只能有一个主键,并且主键不能为 null,不能重复。(可以理解为一种特殊的唯一索引)

在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引且不允许存在null值的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。

2. 二级索引(辅助索引)

二级索引又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置。

唯一索引,普通索引,前缀索引等索引属于二级索引。

  • 唯一索引(Unique Key) :唯一索引也是一种约束。唯一索引的属性列不能出现重复的数据,但是允许数据为 NULL,一张表允许创建多个唯一索引
  • 普通索引(Normal Index) :也叫单列索引,给表中的某一个列创建索引,即一个索引只包含单个列;一个表可以有多个单列索引。普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL。
  • 前缀索引(Prefix) :前缀索引只适用于字符串类型的数据。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小, 因为只取前几个字符。
  • 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术。Mysql5.6 之前只有 MYISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引。

3. 索引的底层数据结构

1. B 树& B+树

B 树也称 B-树,全称为 多路平衡查找树 ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 Balanced (平衡)的意思。

目前大部分数据库系统及文件系统都采用 B-Tree 或其变种 B+Tree 作为索引结构。

  • B树是一种平衡多路查找树,满足平衡二叉树的规律,同时可以拥有多个子树,子树的数量取决于关键字的数量,(关键字数量+1),因此从这个特征来看在存储同样数据量,B树会更低一些。
  • B+树是在B树的基础上做了增强。主要有两点:
    • B树的数据存储在每个节点上,而B+树中的数据存储在叶子节点上,并且通过双向链表的方式对叶子节点的数据进行了连接。
    • B树的子树数量等于关键词数量加1,B+树的子树数量等于关键字的数量。

2. 为什么选择B/B+树,为什么要用 B+树,为什么不用二叉树?

B/B+Tree更适合文件系统的索引/更适合硬盘上查询的数据结构。

  • 1.高度低-->io次数少
  • 2.顺序io只需一次扫描数据 > 随机io-->性能高
  • 3.多路子树,数据量大不能一次性全部加载到内存时,会每次加载树的一个节点,由于多路子树的节点数量多于普通树的节点,所以每次加载的数量更多-->速度更快

为什么不是一般二叉树?  

二者存储数据的结构可以看出,二叉树随着数据的增加,树的高度会越来越高,而B+树是越来越胖。

树的高度越来越高,增加了I/O次数,导致查询效率减低。而B+树随着数据量的增加,树的宽度越来越大,这样空间利用率更高,可减少I/O次数,查询效率较快。

我们知道,在内存比在磁盘的数据,查询效率快得多。如果树这种数据结构作为索引,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块,但是平衡二叉树可是每个节点只存储一个键值和数据的,如果是B树,可以存储更多的节点数据,每个节点包含多个数据,树的高度也会降低,因此读取磁盘的次数就降下来啦,查询效率就快啦。

为什么不是B树而是B+树呢?

  • B+树的层级更少。相较于B树,B+树每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快。
  • B+树查询效率更高。B+树使用双向链表串连所有叶子节点,而且数据是按照顺序排列的,区间查询效率更高(因为所有数据都在B+树的叶子节点,扫描数据库只需扫一遍叶子结点就行了),但是B树则需要通过中序遍历才能完成查询范围的查找。
  • B+树查询效率更稳定。B+树只有叶子结点存放数据的data值,非叶子节点上只存储key值信息,B+树每次都必须查询到叶子节点才能找到数据,而B树查询的数据可能不在叶子节点,也可能在,这样就会造成查询的效率的不稳定。
  • B+树的磁盘读写代价更小。B+树的内部节点只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度,因此通常B+树矮更胖,查询产生的I/O更少。B树节点中不仅存了数据的key值,还有data值,而每一个页的存储空间是有限的(16KB),如果data数据较大时将会导致一个页能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。

3. 不同引擎对于B+树的实现

B+Tree在两种存储引擎的实现方式是不同的。  

  • MylSAM:B+Tree叶节点的「data域存放的是数据记录的地址」

在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录。这被称为“非聚簇索引”

  • InnoDB:其数据文件「本身就是索引文件」。

相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,「树的叶节点data域保存了完整的数据记录」。

这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”。而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。

4. B+ Tree索引和Hash索引区别?

  • B+树可以进行范围搜索,hash索引只支持=的操作符,等值查询。
  • B+树支持order by进行排序,hash索引没办法利用索引完成排序。
  • B+树支持多列联合索引的最左匹配规则。hash索引不支持
  • 如果有大量重复健值得情况下,hash索引的效率会很低,因为哈希冲突问题。
  • B+树使用like进行模糊查询的时候,like后面%开头可以起到优化作用,Hash索引不行。

Hash索引的缺点

  • 查询性能受hash冲突率影响,性能不稳定
  • 只能通过等值匹配的方式查询,不能范围查询
  • 结构存储上没有顺序,查询时排序无法支持

InnoDB引擎有一个特殊额功能叫做“自适应哈希索引”,当 InnoDB注意到某些索引值被使用得非常频繁时,它会在内存中基于B-Tree索引之上再创建一个哈希索引,这样就让B-Tree索引页具有哈希索引的一些优点,比如快速的哈希查找。

4. 聚集索引和非聚集索引

聚集索引即索引结构和数据一起存放的索引。主键索引属于聚集索引。

聚集索引是依据主键创建的索引,除了主键以外的其他索引,都是非聚集索引。

不是单独的索引类型,是一种数据存储方式。

1. 介绍聚集索引和非聚集索引

在InnoDB引擎里,一张表的数据对应的物理文件本身是按照B+树来组织的,而聚集索引就是按照每张表的一个主键来构建这样一个B+树,叶子节点里面存储了表里面的每一行数据记录,基于这样一个特征,聚集索引不仅仅是一种索引类型,还是一种数据存储方式

同时意味着每张表里必须有主键,没有主键的话innodb会默认添加一个隐藏列作为主键索引来存储这个表的数据行。一般情况建议使用自增id作为主键,因为id本身具有连续性,对应数据也会按照顺序去存储到磁盘上,写入和检索性能都很高。

innodb里只能存在一个聚集索引,如果有多个,那意味着这个表会有多个副本,这不仅会造成空间浪费,还会导致数据的维护困难。

innodb主键索引存储了一个表的完整数据,主键和行记录放在同一个叶节点,找到了主键也就找到了行记录。所以如果是基于非聚集索引去查找一条数据,最终还是需要访问主键索引来进行检索。

跟MyISAM引擎的非聚集索引不同的是,MyISAM叶节点保存的是地址,而InnoDB是主键,InnoDB非聚集索引的索引文件和数据文件分开存储,索引文件的叶节点只保存主键,在查找时,要先找到叶节点中的主键,再根据主键去主索引文件查找详细行记录;

2. 回表查询

上述InnoDB引擎中,非主键索引查找数据时需要先找到主键,再根据主键查找具体行数据,这种现象叫回表查询

如何解决:覆盖索引,即将查询sql中的字段添加到联合索引里面,只要保证查询语句里面的字段都在索引文件中,就无需进行回表查询;让索引范围覆盖住我们select 的范围,就不会发生回表查询。

比方说有个用户表,有id、name、age、addr四个字段,其中id为主键,主键自带主键索引,无需创建

值1:1、小张、18、成都;

值2:2、小黄、20、北京;

这种查询就必须先在索引文件中找到name为小张的索引节点,很明显这个节点里面只有id,因为这张表只有主键索引,再根据id去数据文件查找具体数据。

如果把name、age、addr建立到联合索引,在找到name为小张的索引节点时,发现里面已经有了我们所需要的age、addr,就无需再到数据文件查找;

当然实际开发中,不可能把所有字段建立到联合索引,应根据实际业务场景,把经常需要查询的字段建立到联合索引即可。

3. 索引下推

索引下推是 MySQL 5.6 版本中提供的一项索引优化功能,可以在非聚簇索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表次数。 

不使用索引条件下推优化时的查询过程

获取下一行,首先读取索引信息,然后根据索引将整行数据读取出来。
然后通过where条件判断当前数据是否符合条件,符合返回数据。

使用索引条件下推优化时的查询过程

获取下一行的索引信息。
检查索引中存储的列信息是否符合索引条件,如果符合将整行数据读取出来,如果不符合跳过读取下一行。
用剩余的判断条件,判断此行数据是否符合要求,符合要求返回数据。

5. 联合索引和覆盖索引

1. 覆盖索引

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。我们知道在 InnoDB 存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!

覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。

2. 联合索引

使用表中的多个字段创建索引,就是 联合索引,也叫 组合索引 或 复合索引

覆盖索引是通过联合索引来实现的。

3. 最左前缀匹配原则

最左前缀匹配原则指的是,在使用联合索引时,MySQL 会根据联合索引中的字段顺序,从左到右依次到查询条件中去匹配,如果查询条件中存在与联合索引中最左侧字段相匹配的字段,则就会使用该字段过滤一批数据,直至联合索引中全部字段匹配完成,或者在执行过程中遇到范围查询,如 >、<、between 和 以%开头的like查询 等条件,才会停止匹配。

如有索引 (a,b,c,d),查询条件 a=1 and b=2 and c>3 and d=4,则会在每个节点依次命中a、b、c,无法命中d。(c已经是范围查询了,d肯定是排不了序了)

因此,列的排列顺序决定了可命中索引的列数。

6. 创建索引及索引的优化

1.选择合适的字段创建索引:

  • 不为 NULL 的字段 
  • 被频繁查询的字段 
  • 被作为条件查询的字段 
  • 频繁需要排序的字段
  • 被经常频繁用于连接的字段

2.被频繁更新的字段应该慎重建立索引。

3.尽可能的考虑建立联合索引而不是单列索引。

4.注意避免冗余索引 。

5.考虑在字符串类型的字段上使用前缀索引代替普通索引。

7. MySQL 为表字段添加索引

// 主键索引
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
 
//唯一索引
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
 
//普通索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
 
//全文索引
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
 
//联合索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
 

8、索引原则

  • 索引不是越多越好。
  • 不要对进程变动数据加索引。
  • 小数据量的表不需要加索引。
  • 索引一般加在常用来查询的字段上!

索引的数据结构
        Hash 类型的索引
        Btree : InnoDB 的默认数据结构~

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

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

相关文章

在Linux运行LaTeX

共有三个步骤1. 装LaTexTeX Live - TeX Users Group 下载对应版本安装包安装 文件比较大&#xff0c;这步花的时间多一点&#xff0c;不过也不会太多&#xff0c;感觉5分钟十分钟的样子吧 2. 装TexStidio 这一步是安装一个类似在windows系统下的TaTeX GUI软件 图标是这样3. 配置…

安装hadoop

前置需要安装java rz tar -zxvf jdk-8u381-linux-x64.tar.gz -C / ln -s /jdk1.8.0_381/ /jdk # rm jdk-8u381-linux-x64.tar.gzexport JAVA_HOME/jdk export PATH$PATH:$JAVA_HOME/binhadoop可以选择清华源或者官网下载官网 rz # 上传hadoop包到机器 tar -zxvf hadoop-3.3.6…

精致旅游公司Treker网页设计 html模板

一、需求分析 旅游网站通常具有多种功能&#xff0c;以下是一些常见的旅游网站功能&#xff1a; 酒店预订&#xff1a;旅游网站可以提供酒店预订服务&#xff0c;让用户搜索并预订符合其需求和预算的酒店房间。 机票预订&#xff1a;用户可以通过旅游网站搜索、比较和预订机票…

【数据结构】链式家族的成员——循环链表与静态链表

循环链表与静态链表 导言一、循环链表1.1 循环单链表1.2 循环双链表 二、静态链表2.1 静态链表的创建2.2 静态链表的初始化2.3 小结 结语 导言 大家好&#xff01;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 经过前面的介绍&#xff0c;相信大家对链式家族的…

企业如何做好内容?媒介盒子分享

在个性化算法的支持下&#xff0c;企业通过创作优质内容使消费者主动选择企业的时代已经来临&#xff0c;对于中小企业来说&#xff0c;这是能够低成本进行营销的好机会。但是有许多企业对内容的理解依旧是片面的&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;企业如何做…

【MYSQL】-函数

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

《微信小程序开发从入门到实战》学习六十七

6.6 网络API 部分小程序服务端不是用云开发技术实现&#xff0c;而是由开发人员使用后端开发语言实现。 在小程序用网络API与&#xff08;开发人员使后端开发语言建设的&#xff09;服务端进行交互&#xff0c;可与服务端交换数据、上传或下载文件。 6.6.1 服务器域名配置 …

zookeeper之集群搭建

1. 集群角色 zookeeper集群下&#xff0c;有3种角色&#xff0c;分别是领导者(Leader)、跟随着(Follower)、观察者(Observer)。接下来我们分别看一下这三种角色的作用。 领导者(Leader)&#xff1a; 事务请求&#xff08;写操作&#xff09;的唯一调度者和处理者&#xff0c;保…

LTSpice仿真场效应管(FET)的方法

刚开始用LTSpice学习电子电路&#xff0c;发现添加 JFET 和 MOSFET 的方法与添加普通原件不一样&#xff0c;需要分两步完成。 第一步&#xff1a;选择元件 njf、pjf、nmos、pmos&#xff0c;分别对应 N Channel 的 JFET 和 P Channel 的 JFET&#xff1b;N Channel 的 MOSFET…

SpringMVC学习与开发(四)

注&#xff1a;此为笔者学习狂神说SpringMVC的笔记&#xff0c;其中包含个人的笔记和理解&#xff0c;仅做学习笔记之用&#xff0c;更多详细资讯请出门左拐B站&#xff1a;狂神说!!! 11、Ajax初体验 1、伪造Ajax 结果&#xff1a;并未有xhr异步请求 <!DOCTYPE html> &…

组合总和[中等]

一、题目 给你一个 无重复元素 的整数数组candidates和一个目标整数target&#xff0c;找出candidates中可以使数字和为目标数target的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates中的 同一个 数字可以 无限制重复被选取 。如果…

C#使用switch语句更改窗体颜色

目录 一、示例 二、生成 用switch多路选择语句及窗体的BackColor属性更改窗体的BackColor属性。该属性用于获取或设置控件的背景颜色。 可以使用Color结构的静态属性获取Color对象&#xff0c;如Color.Red&#xff1b;也可以使用Color结构的静态方法Color.FromArgb()&#xf…

『番外篇六』SwiftUI 取得任意视图全局位置的三种方法

概览 在 SwiftUI 开发中,利用描述性代码我们可以很轻松的构建各种丰富多彩的视图。我们可以设置它们的大小、位置、颜色并应用不计其数的修改器。 但是,小伙伴们是否想过在 SwiftUI 中如何获取一个视图的全局位置坐标呢? 在本篇博文中,您将学到如下内容: 概览1. SwiftU…

【docker实战】01 Linux上docker的安装

Docker CE是免费的Docker产品的新名称&#xff0c;Docker CE包含了完整的Docker平台&#xff0c;非常适合开发人员和运维团队构建容器APP。 Ubuntu 14.04/16.04&#xff08;使用 apt-get 进行安装&#xff09; # step 1: 安装必要的一些系统工具 sudo apt-get update sudo ap…

java虚拟机内存管理

文章目录 概要一、jdk7与jdk8内存结构的差异二、程序计数器三、虚拟机栈3.1 什么是虚拟机栈3.2 什么是栈帧3.3 栈帧的组成 四、本地方法栈五、堆5.1 堆的特点5.2 堆的结构5.3 堆的参数配置 六、方法区6.1 方法区结构6.2 运行时常量池 七、元空间 概要 根据 JVM 规范&#xff0…

20231229在Firefly的AIO-3399J开发板的Android11使用挖掘机的DTS配置单前后摄像头ov13850

20231229在Firefly的AIO-3399J开发板的Android11使用挖掘机的DTS配置单前后摄像头ov13850 2023/12/29 11:10 开发板&#xff1a;Firefly的AIO-3399J【RK3399】 SDK&#xff1a;rk3399-android-11-r20211216.tar.xz【Android11】 Android11.0.tar.bz2.aa【ToyBrick】 Android11.…

【软件工程】走进瀑布模型:传统软件开发的经典之路

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; 软件工程 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言&#xff1a; 正文 主要阶段&#xff1a; 优点&#xff1a; 缺点&#xff1a; 应用范围&#xff1a; 结语 我的其他博客 前言&am…

算法训练营Day26

#Java #全排列 #回溯 开源学习资料 Feeling and experiences&#xff1a; 递增子序列&#xff1a;力扣题目链接 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组…

需求分析 :不得不重新去面对的一关。

软件需求分析 背景 深入需求产生的背景明确项目目标了解用户群体 需求优先级 需求的分类与整理明确需求优先级让团队成员都参与到需求分析中来&#xff0c;增加团队合作能力与效率 编写需求文档 整理好的需求编写成详细的需求文档包括需求的描述、输入/输出格式、功能流程…

【数据库系统概论】第7章-数据库设计

文章目录 7.1 数据库设计概述7.2 需求分析7.2.1 需求分析的任务7.2.2 需求分析的难点7.2.2 需求分析的方法7.2.3 数据字典 7.3 概念结构设计7.3.1 概念模型7.3.2 E-R模型7.3.3 概念结构设计 7.4 逻辑结构设计7.4.1 E-R图向关系模型的转换7.4.2 数据模型的优化7.4.3 设计用户子模…