图解MySQL索引(上)—MySQL有中“8种”索引?

关于MySQL索引相关的内容,一直是一个让人头疼的问题,尤其是对于初学者来说。笔者曾在很长一段时间内深陷其中,无法分清“覆盖索引,辅助索引,唯一索引,Hash索引,B-Tree索引……”到底是些什么东西,导致在面试过程中进入比较尴尬的局面。

很多人可能会抱怨”面试造火箭,工作拧螺丝,很多知识都是为了面试学的,工作中根本用不到!“。庆幸的是,MySQL中索引不仅是面试必考知识,还是工作中用到最为频繁的必备技能,在笔者看来,索引是MySQL中性价比最高的一部分内容

由于MySQL中支持多种存储引擎,在不同的存储引擎中实现略微有所差距,索引下文中如果没有特殊声明,默认指的都是InnoDB存储引擎,下文中索引基于这张user表来进行演示。

id name age
001 Lily 18
002 Tom 20
003 Jack 19
004 John 28
005 Alice 24
006 Lucy 21
007 Rose 18
008 Steven 16

一、索引的底层数据结构

首先,索引是高效获取数据的数据结构。就像书中的目录一样,我们可以通过它快速定位到数据所在的位置,从而提高数据查询的效率。

在MySQL中有许多关于索引的名词和概念,对于初学者来说很容易被迷惑。为了方便理解,我建立了一张表,从具体的案例中尝试说清楚这些概念到底是什么。

Hash索引

正如上文中说到,索引是提高查询效率的数据结构,而能够提高查询效率的数据结构有很多,如二叉搜索树,红黑树,跳表,哈希表(散列表)等,而MySQL中用到了B+Tree和散列表(Hash表)作为索引的底层数据结构。

需要注意的是,MySQL并没有显式支持Hash索引,而是作为内部的一种优化,对于热点的数据会自动生成Hash索引,也叫自适应Hash索引

Hash索引在等值查询中,可以O(1)时间复杂度定位到数据,效率非常高,但是不支持范围查询。在许多编程语言以及数据库中都会用到这个数据结构,如Redis支持的Hash数据结构。具体结构如下:

B+Tree索引

提到B+Tree首先不的不提B-Tree,B-Tree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。

B+ 树是基于B-Tree升级后的一种树数据结构,通常用于数据库和操作系统的文件系统中。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入,这与二叉树恰好相反。

MySQL索引的实现也是基于这种高效的数据结构。具体数据结构如下:

笔者首先要声明一下,不要将B树,B-Tree以及B+Tree弄混淆。首先,B-Tree就是B树,中间的“-”是一个中划线,而不是减号,并不存在"B减树"这种数据结构。其次,就是B+Tree和B-Tree实现索引时有两个区别,具体可见下图

①B+Tree只在叶子节点存储数据,而B-Tree的数据存储在各个节点中

②B+Tree的叶子节点间通过指针链接,可以通过遍历叶子节点即可获取所有数据。

B+Tree是一种神奇的数据结构,如果用语言来讲可能会优点费劲,感兴趣的同学可以点击这里进行数据结构可视化,操作一番后想必会有所收获,下图是笔者演示B+Tree的数据插入方式(自下而上)。

二,数据组织方式

根据数据的组织方式,可以分为聚簇索引和非聚簇索引(也叫聚集索引和非聚集索引)。如果是索引组织数据,就称之为聚簇索引,否则称之为非聚簇索引,简单来说索引和数据是否存储在一起

需要注意的是,这种索引划分方式通常用来体现不同存储引擎的组织数据方式的差异(通常指的是InnoDB和MyISAM存储引擎)。而InnoDB中的辅助索引并不能称之为非聚簇索引,关于辅助索引的内容,下文会进行详细介绍。InnoDB中是通过索引来组织数据,为聚簇索引。

而MyISAM中索引和数据文件分开存储,为非聚簇索引。B+Tree的叶子节点存储的是数据存放的地址,而不是具体的数据 。

三,索引字段个数

为了能应对不同的数据检索需求,索引即可以仅包含一个字段,也可以同时包含多个字段。单个字段组成的索引可以称为单值索引,否则称之为复合索引(或者称为组合索引或多值索引)。上文中演示的都是单值索引,所以接下来展示一下复合索引作为对比。

复合索引的索引的数据顺序跟字段的顺序相关,包含多个值的索引中,如果当前面字段的值重复时,将会按照其后面的值进行排序。

四, 是否存储完整数据行

MySQL中是根据主键来组织数据,所以每张表都必须有主键索引,主键索引只能有一个,不能为null同时必须保证唯一性。建表时如果没有指定主键索引,则会自动生成一个隐藏的字段作为主键索引。

如果不是主键索引,则就可以称之为非主键索引,又可以称之为辅助索引,二级索引。主键索引的叶子节点存储了完整的数据行,而非主键索引的叶子节点存储的则是主键索引值,通过非主键索引查询数据时,会先查找到主键索引,然后再到主键索引上去查找对应的数据,这个过程叫做回表(下文中会再次提到)。

五,其他分类

唯一索引

唯一索引,不允许具有索引值相同的行,从而禁止重复的索引或键值。系统在创建该索引时检查是否有重复的键值,并在每次使用 INSERT 或 UPDATE 语句添加数据时进行检查, 如果有重复的值,则会操作失败,抛出异常。

需要注意的时,主键索引一定时唯一索引,而唯一索引不一定时主键索引。唯一索引可以理解为仅仅是将索引设置一个唯一性的属性

覆盖索引

上文提到了一个回表的概念,既如果通过非主键索引查询数据时,会先查询到主键索引的值,然后再去主键索引中查询具体的数据,整个查询流程需要扫描两次索引,显然回表是一个耗时的操作。

为了减少回表次数,再设计索引时我们可以让索引中包含要查询的结果,在辅助索引中检索到数据后直接返回,而不需要进行回表操作。

但是需要注意的是,使用覆盖索引的前提是字段长度比较短,对于值长度较长的字段则不适合使用覆盖索引,原因有很多,比如索引一般存储在内存中,如果占用空间较大,则可能会从磁盘中加载,影响性能。当然还有其他原因,具体情况将会在下一篇文章中介绍。

六,总结

本文从不同维度介绍了MySQL中的索引,索引从不同维度划分可以有很多种名称,但是需要明确一个问题就是,索引的本质是一种数据结构,其他索引的划分则是针对实际应用而言。具体分类如下图所示:

目的是让大家对于索引有个初步且清晰的认识,解决What的问题。后续将会针对Why以及How,进行深入探讨,当然,首先应当能区分本章文章中讲述的概念性问题。

七、Q&A

1. 为什么MySQL索引使用B+Tree实现,而不是搜索二叉树,红黑树或者跳表?

这是一个综合性问题,远不止看起来那么简单,小伙伴们可以把答案写在留言区我们一起探讨,同样笔者将会在下一篇文章中重点介绍为什么,以及如何正确使用索引。

原文地址:https://www.cnblogs.com/liqiangchn/p/12432236.html

时间: 2024-07-30 13:07:06

图解MySQL索引(上)—MySQL有中“8种”索引?的相关文章

MySQL数据库InnoDB存储引擎中的锁机制--转载

原文地址:http://www.uml.org.cn/sjjm/201205302.asp 00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化. 锁就是其中的一种机制.我们用商场的试衣间来做一个比喻.试衣间供许多消费者使用.因此可能有多个消费者同时要试衣服.为了避免冲突,试衣间的门上装了锁.试衣服的人在里边锁住,其他人就不能从外边打开了.只有里边的人开门出来,外边的人才能进去. - 锁的基本类型 数据库上的操作可以归纳为两中,读和写.多个

MySQL数据库InnoDB存储引擎中的锁机制

MySQL数据库InnoDB存储引擎中的锁机制    http://www.uml.org.cn/sjjm/201205302.asp   00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化. 锁就是其中的一种机制.我们用商场的试衣间来做一个比喻.试衣间供许多消费者使用.因此可能有多个消费者同时要试衣服.为了避免冲突,试衣间的门上装了锁.试衣服的人在里边锁住,其他人就不能从外边打开了.只有里边的人开门出来,外边的人才能进去. - 锁的基本

MySQL数据库 上

MySQL数据库 (上) MySQL数据类型:数值类型.日期和时间类型.字符串类型 1.数值类型 注:BIT数据类型保存位字段值,并且支持MyISAM.MEMORY.InnoDB和BDB表 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767) (0,65 535) 大整数值 MEDIUMINT 3 字节 (-8 388 608,8 388 607) (0,16 77

MySQL系列(四) MySQL的索引和算法

11 表结构 表是关于特定实体的数据集合,这也是关系型数据库的核心. 在InnoDB中,表都是根据主键顺序组织存放的,这种存储方式的表成为索引组织表. 所有数据都被逻辑的存放在一个空间中,称之为表空间 tablespace. 表空间又由段 segment, 区 extent, 页page 组成. 页在一些文档中有时也称之为块 block. 一个区一般为1M,一个页总是16KB,即一个区一共有64个连续的页. InnoDB中数据是按行进行存放的.每个页存放的行是有硬性规定规定的,最多运行存放16

MySQL高级知识- MySQL的架构介绍

[TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性. Mysql是开源的,所以你不需要支付额外的费用. Mysql支持大型的数据库.可以处理拥有上千万条记录的大型数据库. MySQL使用标准的SQL数据语言形式. Mysql可以允许于多个系统上,并且支持多种语言.这些编程语言包括C.C+

索引键的唯一性(4/4):非唯一聚集索引上的唯一和非唯一非聚集索引

在上一篇文章里,我谈了唯一聚集索引上的唯一和非唯一非聚集索引的区别.在这篇文章里,我想谈下非唯一聚集索引上的唯一和非唯一聚集索引的区别.我们都知道,SQL Server内部把非唯一聚集索引当作唯一聚集索引处理的.如果你定义了一个非唯一聚集索引,SQL Server会增加叫做uniquifier到你的索引记录,它导致你聚集索引的导航结构(B树的非叶子层)里,每条索引行都要用到4 bytes的开销. 下列代码再次创建我们的Customers表,这次在它上面定义非唯一聚集索引,最后定义2个非聚集索引,

mysql中能够使用索引的典型场景

mysql 演示数据库:http://downloads.mysql.com/docs/sakila-db.zip 匹配全值 explain select * from rental where rental_date='2005-05-25 17:22:10' and inventory_id=373 and customer_id=343 匹配值的范围查询 explain select * from rental where customer_id >= 373 and customer_i

MYSQL中的普通索引,主健,唯一,全文索引区别

MYSQL索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的记录数量越多,这个操作的代价就越高.如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置.如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍. 总体分析 PRIMARY, INDEX, UNIQUE 这3种是一类 PRIMARY 主键. 就

高性能MySQL中的三星索引

高性能MySQL中的三星索引 我对此提出了深深的疑问: 一星:相关的记录指的是什么??(相关这个词很深奥,“相关部门”是什么部门) 二星:如果建立了B-Tree(B+Tree)索引,数据就有序了.三星:索引的列包含了查询需要所有的列?根本不需要在where查询条件所有的列上建立索引! 我认为一星和二星的rows应该是columns,索引不关具体的数据行,只与查询的列有关.这样也与High Performance MySQL 后面提到的多列索引的观点相符合,特别是二星评估. 个人的观点: 评估一个