今天我突然想起了之前数据库的索引,但是那时候没有深入学习过,只是知道它有利于数据库的搜索。 于是我今天去b站上找了视频搜索了一下,才明白了它的原理和用法。
一. 定义
索引是帮助MySQL高效获取数据的数据结构。在 MySQL 中,所有的数据存储在磁盘上,索引通过构建特定的数据结构(如 B+ 树、哈希表等),减少了查询时需要扫描的数据量,从而加速数据检索过程。
比如对于上述的user表来说,如果我们查询name为“Grace”的数据,不添加索引的时候会从上往下一个一个查,类似于for(int i = 0; i < size; i++)一样。 那对于索引创建之后是什么样呢?
二. 索引的机制
目前的MySQL提供了以下几个索引:
-
BTREE 索引 :
应用范围广,是 MySQL 里基础且常用的索引类型,依托 B + 树数据结构实现,能适配多种查询场景,多数存储引擎默认可支持基于它构建索引来优化查询。 -
HASH 索引 :
依赖哈希算法,仅 Memory 存储引擎专属支持,通过哈希映射快速定位数据,不过适用场景相对单一,对范围等复杂查询适配性弱。 -
空间索引(R-tree 索引 ):
为地理空间数据设计,曾是 MyISAM 引擎特色索引类型,借助 R - tree 结构管理空间数据,因应用场景较窄(聚焦空间查询),日常一般不常深入使用介绍。 -
全文索引 :
起初作为 MyISAM 引擎特有的文本检索优化手段,用于高效全文内容查询;从 MySQL 5.6 起,InnoDB 也增添了对它的支持,拓宽了文本检索在不同引擎的应用。
这些概念可能看不太懂,但是你只需要知道以上我们主要应用的是BTREE索引,它是依托的B+树的数据结构实现的。
那么这就引出了一个新的问题,B+树是的基本结构是怎么样的呢?
我们先讲一下B树的概念吧。
首先先简单介绍下B树的一些规则:
1. B 树的基本定义
B 树是一种m 阶 树(m≥2,m 为正整数),它是一棵平衡的多路查找树,满足以下规则:
2. 节点结构规则
(1) 节点数据存储:
- 每个节点最多包含 m-1 个关键字(数据值),且这些关键字按升序排列(如 k₁ < k₂ < ... < kₙ,n≤m-1)。
- 每个节点若有 n 个关键字,则对应 n+1 个子节点(用于指向子树)。
- 叶子节点的子节点为空指针,所有叶子节点在同一高度(即处于同一层),以此保证树的平衡。
(2) 非叶子节点的子树关系:
- 对于节点中的第 i 个关键字 kᵢ,其左子树的所有关键字均小于 kᵢ,右子树的所有关键字均大于 kᵢ。
- 例如:若节点关键字为 [3,7],则左子树所有值 < 3,中间子树 3 < 值 < 7,右子树所有值 > 7。
- 这一关系递归适用于所有子树,且结合 “所有叶子节点在同一高度” 的特性,确保从根节点到任意叶子节点的路径长度一致,维持树的平衡性。
下边我们看一下例子(以m = 4的B树为例):
错误示例1: :该节点最多只能有m - 1 = 3个节点。正确的应该去掉节点保持节点数量<=3个
错误示例2: : 该节点虽然满足了至多有m - 1个节点,但是不满足升序排列(28 > 20);正确的应该把20和28位置互换
(3) B树的插入
现在有10,20,30,40,50,60,70,80,90,100十个数
刚开始前三个数正常插入,得到
随后插入40超过m-1个字数限制
需要提取出节点向上移动(这里提取的是第m/2个上取整节点,即第2个节点。 但注意,我这里的2不是从0开始的,而是从1开始的,即20)得到
随后同理,一步一步插入,插入完60得到
进一步,插入70, 80, 90后得到
这时候,再插入100, 根据我们前边学的,应该进入90后边,然后 再取第二个元素80放入上边,但是这时候会发现根节点也变成了(20 40 60 80)超过了限制。这时候不要慌,我们还是按照正常的操作进行分裂
那大概B树的插入操作就是这样。由于我们主要讲索引,然后对于B树的删除操作我就不讲了。
(4) B树的查询
然后是对于查询操作,比如我要查询90,那我就从根节点开始比较40 < 90进入右子节点,遍历之后发现90 < 100进入100的左子节点,随后遍历70->80->90得到最终结果。 我们会发现我们只查询3次,而对于未添加索引的时候,我们却要从10--90查询9次。
3. B+树与索引
(1) B+树与B树的区别
那按照上述来说,B+树无非在插入节点时判断的不是节点中的数据<m而是<=m。
(2) 存储数据
对于B树来说,他的每个节点都存储数据。 比如我们之前举的例子,对于10-100中的每个数据他不仅有索引指针,还有指向的具体数据。
但对于B+树来说,我们在非叶节点只存储索引指针,而不存储索引数据, 所以任何数据的查取都必须到达叶子节点。但如果我们按照上述的图来,查询20的时候只能停在20的index中,得不到msg信息。这时候就要注意到之前是B树结构,下图是B+的结构。
现在我们确实可以查找到对应的数据了,但是我如果要查询范围数据呢?比如10-50. 难道我要一个一个找吗?这时候就加上了指针。
就可以从前往后查询啦。
至此基本的原理就🆗了。
4. 索引的基本分类:
单值索引:
仅包含单个数据列,一张表可创建多个。基于 B + 树等结构实现,适配单字段精确查询、排序等场景,是基础常用的索引类型,能提升单字段查询效率。
唯一索引:
要求索引列值唯一(允许 NULL),重复非空值会被阻止。多基于 B + 树实现,既用于数据唯一性约束,也能加速查询,适用于需唯一标识的字段。
复合索引:
包含多个数据列,遵循 “最左匹配原则”。基于 B + 树构建,适用于多字段组合查询,合理设计列顺序可提升效率,不契合规则则可能失效。
三. 操作命令
(1) 创建索引
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
这一条相信大家都见过了,就是创建主键。创建主键时就对这个列进行了索引创建。
-- 普通索引
CREATE INDEX index_name ON table_name(column_name);
-- 唯一索引(确保列值唯一)
CREATE UNIQUE INDEX index_name ON table_name(column_name);
这两条命令是创建普通索引和唯一索引的,他们俩的区别就是加不加unique。
-- 复合索引(多列组合)
CREATE INDEX index_name ON table_name(column1, column2, ...);
比较特殊的是这一条,创建复合索引。 他创建的时候可不仅仅是对[column1,colomn2...]进行索引创建,而是采用最左匹配原则,分别对[colomn1], [colomn1, colomn2] , [colomn1 ,colomn2 , colomn3]...创建索引
(2)查询索引
SHOW INDEX FROM table_name;
这是查询索引的内容
(3) 删除索引
-- 删除普通索引、唯一索引、复合索引
DROP INDEX index_name ON table_name;
这是删除索引的内容。
(4) 总结
不知道大家发现没有,我们对索引创建的命令drop、show、create等关键字都和对表的操作是一样的,也更方便记忆。
四. 结尾
最后我要提一嘴的是,尽管索引有利于我们查询操作,但它并不是越多越好,因为我们每次的插入和删除等对数据操作的时候,都要对索引进行维护。
通过以上部分的定义、索引机制和操作命令的介绍,希望大家能够对索引有进一步了解。