一、什么是索引

在数据库中,索引的含义与日常意义上的“索引”一词并无多大区别(想想小时候查字典),它是用于提高数据库表数据访问速度的数据库对象。

总而言之,索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据

  • 索引可以避免全表扫描。多数查询可以仅扫描少量索引页及数据页,而不是遍历所有数据页。
  • 对于非聚集索引,有些查询甚至可以不访问数据页
  • 聚集索引可以避免数据插入操作集中于表的最后一个数据页
  • 一些情况下,索引还可用于避免排序操作

当然,众所周知,虽然索引可以提高查询速度,但是它们也会导致数据库系统「更新数据」的性能下降,因为大部分数据更新需要同时更新索引。

二、索引的适用场景

什么样的字段适合创建索引?

1、表的主键、外键一般必须有索引
2、数据量超过300的表应该有索引(不知道是什么依据,难道是经验之谈?)
3、经常与其他表进行连接的表,在连接字段上应该建立索引
4、经常出现在where子句中的字段,加快判断速度,特别是大表的字段,应该建立索引
5、经常用于排序的列上
6、经常用在范围内搜索的列上创建索引

什么场景不适合创建索引?

1、对于那些在查询中很少使用的列
2、对于那些只有取值种类较少的列也不应该增加索引,例如性别
3、对于那些定义为text、image和bit数据类型的列不应该增加索引。
这些列的数据量要么相当大,要么取值很少。
4、当修改性能远远大于检索性能时,不应该创建索引。修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。
5、不会出现在where条件中的字段不该建立索引

三、索引的分类

1、从存储结构上来划分:

BTree索引(B-Tree或B+Tree索引),Hash索引,full-index全文索引
这里的存储结构是指索引的组织形式,比如B+Tree索引,就是将索引页当做一个一个节点,然后以B+树的形式组织起来

2、从应用层次来分:

普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引:索引列的值必须唯一,但允许有空值
复合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并

3、根据中数据的物理顺序与键值的逻辑(索引)顺序关系:

聚集索引:并不是一种单独的索引类型,而是一种数据存储方式。
非聚集索引:不是聚簇索引,就是非聚簇索引,或者叫辅助索引

聚集索引和非聚集索引的差别,下面会有更加详细的说明。

四、索引的数据结构

一条索引记录中包含的基本信息包括:键值(即你定义索引时指定的所有字段的值)+逻辑指针(指向数据页或者另一索引页)

通常状况下,由于索引记录仅包含索引字段值以及4-9字节的指针,索引实体比真实的数据行要小许多,索引页相较数据页来说要密集许多。一个索引页可以存储数量更多的索引记录,这意味着在索引中查找时在I/O上占很大的优势,理解这一点有助于从本质上了解使用索引的优势。

四、InnoDB中索引的实现

MySQL默认存储引擎InnoDB支持常见的几种索引:

  • B+树索引
  • 全文索引
  • 哈希索引

其中,对于频繁访问的表,InnoDB会自动的生成哈希索引,不能认为干预是否在一张表中生成哈希索引

五、InnoDB的B+树索引

数据库的B+树索引分为聚集索引和辅助索引或者叫非聚集索引。二者不同的地方是叶子节点存放的是否是一整行的信息。

聚集索引

表数据按照索引的顺序来存储的。
对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。
当定义下来数据的逻辑顺序时,聚集索引能够比较快速的访问针对范围值的查询非聚集索引

非聚集索引

表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,该层紧邻数据页,其行数量与数据表行数据量一致。

在一张表上只能创建一个聚集索引,因为真实数据的物理顺序只可能是一种。

5.1、聚集索引

在聚集索引中,叶结点也称为数据结点数据页,所有数据行的存储顺序与索引的存储顺序一致。

如上图,我们在名字字段上建立聚集索引,当需要在根据此字段查找特定的记录时,数据库系统会根据特定的系统表查找的此索引的根,然后根据指针查找下一个,直到找到。例如我们要查询“Green”,由于它介于[Bennet,Karsen],据此我们找到了索引页1007,在该页中“Green”介于[Greane, Hunter]间,据此我们找到叶结点1133(也即数据结点),并最终在此页中找以了目标数据行。

此次查询的IO包括3个索引页的查询(其中最后一次实际上是在数据页中查询)。这里的查找可能是从磁盘读取(Physical Read)或是从缓存中读取(Logical Read),如果此表访问频率较高,那么索引树中较高层的索引很可能在缓存中被找到。所以真正的IO可能小于上面的情况。

5.2、非聚集索引

非InnoDB实现:

非聚集索引与聚集索引相比:

  • 叶子结点并非数据结点
  • 叶子结点为每一真正的数据行存储一个“键-指针”对
  • 叶子结点中还存储了一个指针偏移量,根据页指针及指针偏移量可以定位到具体的数据行。
  • 类似的,在除叶结点外的其它索引结点,存储的也是类似的内容,只不过它是指向下一级的索引页的。

聚集索引是一种稀疏索引,数据页上一级的索引页存储的是页指针,而不是行指针。

而对于非聚集索引,则是密集索引,在数据页的上一级索引页它为每一个数据行存储一条索引记录。

对于根与中间级的索引记录,它的结构包括:

  • 索引字段值
  • RowId(即对应数据页的页指针+指针偏移量)。在高层的索引页中包含RowId是为了当索引允许重复值时,当更改数据时精确定位数据行。
  • 下一级索引页的指针

对于叶子层的索引对象,它的结构包括:

  • 索引字段值
  • RowId

针对上图,如果我们同样查找“Green”,那么一次查询操作将包含以下IO: 3个索引页的读取+1个数据页的读取。同样,由于缓存的关系,真实的IO实际可能要小于上面列出的。

InnoDB实现:

在InnoDB中,非聚集索引的叶子节点并不包含行记录的全部信息,除了包含键值以外,还有包含了一个书签bookmark,本质上,bookmark就是相应行数据的「聚集索引键」

在进行查找时,本质上是从非主键->主键->行记录的查找过程

辅助索引的存在并不影的数据在聚集索引中的组织。因此每张表上可以有多个辅助索引。当通过辅助索引来查找数据时,InnoDB存储引擎会遍历辅助索引并通过叶节点的指针获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录。

举例来说。如果在一一棵高度为3的辅助索引树中查找数据,那需要对这个辅助索引树遍历3次找到指定的主键,如果聚集索引的高度同样为3,那么需要对聚集索引进行三次查找,最终找到一个记录所在的页,因此一共需要进行6次逻辑IO才能得到最终的逻辑页。

六、简单总结下

  1. InnoDB使用B+Tree作为索引数据结构。
  2. 从物理存储结构上说,B-Tree和B+Tree都以页(4K)来划分节点的大小,但是由于B+Tree中中间节点不存储数据,因此B+Tree能够在同样大小的节点中,存储更多的key,提高查找效率。
  3. 影响MySQL查找性能的主要还是磁盘IO次数,大部分是磁头移动到指定磁道的时间花费。
  4. InnoDB存储引擎下索引的实现,(辅助索引)全部是依赖于主索引建立的(辅助索引中叶子结点存储的并不是数据的地址,还是主索引的值,因此,所有依赖于辅助索引的都是先根据辅助索引查到主索引,再根据主索引查数据的地址)。

部分参考文献

漫谈数据库索引

MySQL技术内幕 (豆瓣)

mysql索引的新手入门详解

深入理解MySQL索引原理和实现

爪哇滑小稽:面试的时候怎么和面试官讲解你对MySQL索引的理解

聚集索引和非聚集索引的区别底层_数据库-索引相关相关推荐

  1. mysql创建非聚集索引_一文看懂聚集索引和非聚集索引的区别

    一.深入浅出理解索引结构 实际上,可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclu ...

  2. mysql创建非聚集索引_聚集索引和非聚集索引的区别

    作者:riemann riemann.blog.csdn.net/article/details/90324846 一.深入浅出理解索引结构 实际上,可以把索引理解为一种特殊的目录.微软的SQL SE ...

  3. 聚集索引和非聚集索引的区别有哪些

    SQL SERVER提供了两种索引:聚集索引和非聚集索引.其中聚集索引表示表中存储的数据按照索引的顺序存储,检索效率比非聚集索引高,但对数据更新影响较 大.非聚集索引表示数据存储在一个地方,索引存储在 ...

  4. mysql聚合索引跟非聚合索引的区别_聚集索引和非聚集索引的区别有哪些

    下面说说索引使用的几个误区和问题 第一:聚集索引的约束是唯一性,是否要求字段也是唯一的呢? 分析:如果认为是的朋友,可能是受系统默认设置的影响,一般我们指定一个表的主键,如果这个表之前没有聚集索引,同 ...

  5. 主键、聚集索引、非聚集索引区别

    下面是一个简单的比较表   主键 聚集索引 用途 强制表的实体完整性 对数据行的排序,方便查询用 一个表多少个 一个表最多一个主键 一个表最多一个聚集索引 是否允许多个字段来定义 一个主键可以多个字段 ...

  6. 聚集索引和非聚集索引的区别?

    实际上,您可以把索引理解为一种特殊的目录.微软的SQL   SERVER提供了两种索引:聚集索引(clustered   index,也称聚类索引.簇集索引)和非聚集索引(nonclustered   ...

  7. mysql聚集索引和非聚集索引的区别_聚集索引与非聚集索引的总结

    一.索引简介 众所周知,索引是关系型数据库中给数据库表中一列或多列的值排序后的存储结构,SQL的主流索引结构有B+树以及Hash结构,聚集索引以及非聚集索引用的是B+树索引.这篇文章会总结SQL Se ...

  8. Mysql 聚集索引和非聚集索引区别

    1)聚集索引和非聚集索引区别------------聚簇索引和非聚簇索引区别 1.在InnoDb中主键索引即为聚集索引,数据存储在B+树的叶子节点,索引和数据放在一起 2.非聚集索引:指的是非主键索引 ...

  9. 什么是聚集索引和非聚集索引及其两者区别?

    一.聚集索引 定义:数据行的物理顺序与列值(一般是主键的那一列)的 逻辑顺序相同,一个表中只能拥有一个聚集索引. 注: 1.由于物理排列方式与聚集索引的顺序相同,所以也就只能建立一个聚集索引了. 2. ...

最新文章

  1. delphi 打包工具_每年帮你省钱20万的砖头打包方式,是你想要的吗?
  2. java oscache 使用_OScache的使用(Java对象)
  3. EntityFramework 7 OrderBy Skip Take-计算排序分页 SQL 翻译
  4. C++ STL容器vector篇(四) vector容器交换, 预留空间
  5. 2020年进入倒计时:一波前端资源送给你~这一年,谢谢自己!
  6. Java之final关键字详解
  7. 力扣-451 根据字符出现频率排序
  8. A - 1 CodeForces - 500A
  9. nandflash驱动详解
  10. python计算个税
  11. 【寒江雪】Go实现代理模式
  12. 痞子衡嵌入式:开启NXP-MCUBootUtility工具的HAB签名功能 - CST(中英双语)
  13. Burp Suite设置浏览器代理
  14. 安卓手机突然很卡_安卓手机为什么很卡 安卓手机卡顿原因分析【详解】
  15. Ubuntu 编译 ZBar
  16. @Scheduled(cron = * * * * * *) cron表达式详解
  17. 保罗·艾伦去世:他是微软帝国缔造者,最慷慨的慈善家
  18. 7寸 android,7英寸Android:华为Smakit S7_华为 S7_手机导购-中关村在线
  19. 【凸优化学习笔记3】几种重要的凸集
  20. IDLE行号设置及linenumbers修改

热门文章

  1. 获取路径传过来的地址 截取参数
  2. ODAC(V9.5.15) 学习笔记(四)TCustomDADataSet(1)
  3. VBA-设置打印页面的范围
  4. C/C++ Socket编程Http下载的简单实现
  5. [译]Chapter 1 - An Introduction to ASP.NET MVC(2)
  6. python第6天作业
  7. Jmeter跨线程组调用变量
  8. 基于vue的nuxt框架cnode社区服务端渲染
  9. 收藏 || 11个超好用的在线检查语法的网站!!!
  10. Djang(在前端仿DjangoAdmin同样效果)