索引是帮忙MySQL 高效获取数据的数据结构(有序)。在数据之外,数据系统还维护着满足特定查找算法的数据结构。这些数据结构以某种方式音乐(指向)数据,这样就可以在这些数据结构傻姑娘实现高级查找算法,这种数据结构就是索引。
优势 | 缺点 |
---|---|
提高数据检索的效率,将低数据IO成本 | 索引列需要占有空间 |
通过索引列对数据进行排序,将低数据排序的成本,将低CPU的消耗 | 索引大大提高查询效率,在更新的时候需要维护索引,效率降低 |
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,按照存储结构分类主要包含以下几种:
索引结构 | 描述 |
---|---|
B+Tree索引 | 最常见的索引类型,大部分引擎都支持B+树索引 |
Hash索引 | 底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询 |
R-tree(空间索引) | 空间索引是MYISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
Full-text(全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES |
B+树(B+tree)是一种常用的平衡树数据结构,也是MySQL中常用的索引结构之一,用于提高数据访问效率。B+树与B树类似,但有着更高的磁盘块利用率和更好的查询性能。
B+树的特点如下:
相对于B树,B+树的区别在于:
B+树通常应用于磁盘上的存储,因为它能够更好地利用磁盘块,减少了磁盘I/O操作的次数。当数据量较大时,B+树能够更快地查询到数据。
在MySQL中,使用B+树索引结构的表通常有一个叶子节点包含所有数据的指针,以及多个索引节点来加速查找。这些索引节点仅仅是用来定位叶子节点的位置,不存储具体的数据。B+树索引可以提高查询性能,特别是对于范围查询等操作,但对于大量的更新操作,B+树索引会比较慢,因为更新数据时需要不断地调整索引结构。
如下图2.1-1所示:
B+树一个节点对应一页/块,页为InnoDB引擎逻辑存储结构中固定大小的存储结构。每个非叶子结点不用存储数据,可以存储更多的key,同样数据量大情况下,树的高度自然更低,查询效率相应更高。
InnoDB引擎逻辑存储结构,如下图2.1-2所示:
哈希索引(hash index)基于哈希表实现。哈希索引通过Hash算法(直接定址法、平方取中法、折叠法、除数取余法、随机数法)将数据库的索引列数据转换成定长的哈希码作为key,将这条数据的行的地址作为value一并存入Hash表的对应位置。
在MySQL中,只有Memeory引擎显式的支持哈希索引,这也是Memory引擎表的默认索引结构,Memeory同时也支持B-Tree索引。并且,Memory引擎支持非唯一哈希索引,如果多个列的哈希值相同(或者发生了Hash碰撞),索引会在对应Hash键下以链表形式存储多个记录地址。
Hash索引的特点:
存储引擎支持:
在MySQL重,支持hash索引的是Memory引擎,而Inno DB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。
问题1:为什么Inno DB存储引擎选择使用B+Tree索引结构?
主要分类如下表3-1所示:
分类 | 含义 | 特点 | 关键字 |
---|---|---|---|
主键索引 | 针对于表中主键创建的索引 | 默认自动创建,只能由一个 | PRIMARY |
唯一索引 | 限制同一表中某数据列值不能重复 | 可以有多个 | UNIQUE |
常规索引 | 快速定位特定数据 | 可以有多个 | |
全文索引 | 全文索引查找的是文本中的关键词,而不是比较索引中的值 | 可以有多个 | FULLTEXt |
需要根据具体场景和查询需求来选择合适的索引类型。选择适当的索引类型可以有效地提高数据库的查询效率和性能
InnoDB存储引擎中,根据所有的存储形式,又可以分为以下两种:
分类 | 含义 | 特点 |
---|---|---|
聚集索引 | 将数据存储和索引放在一起,索引结构的叶子结点保存了行数据 | 必须有,而且只有一个 |
二级索引 | 将数据和索引分开存储,索引结构的叶子结点关联的是对应的主键 | 可以存在多个 |
聚集索引选取规则:
示例表及结构如下图3.2-1所示:
接下来我们该SQL语句select * from user where name='Arm'
的执行过程,如下图3.2-2所示:
具体过程如下:
回表查询:先在二级索引中查找数据,找到主键。然后在到聚集索引中根据主键获取数据的方式,称为回表查询。
示例表同#3中user表
select * from user where id=10;
select * from user where name='Arm';
-- id为主键,name字段创建有索引
回答:第一条SQL语句执行效率高;
解析:
B+tree存储结构如下图4-1所示所示:
假设: 一行数据大小为1k,一页中可以存储16行这样的数据。InnoDB的指针占用6个字节的空
间,假设主键即使为bigint,占用字节数为8。 高度为2:
n ∗ 8 + ( n + 1 ) ∗ 6 = 16 ∗ 1024 , 算出 n 约为 1170 ; 1171 ∗ 16 = 18736 n*8+(n+1)*6=16*1024, 算出n约为 1170; 1171* 16 = 18736 n∗8+(n+1)∗6=16∗1024,算出n约为1170;1171∗16=18736 也就是说,如果树的高度为2,则可以存储 18000 多条记录。
高度为3:
1171 * 1171 * 16 = 21939856 也就是说,如果树的高度为3,则可以存储 2200w 左右的记录。一行数据大小为rowSize,一页大小为16k,InnoDB的指针占有6字节大小,主键类型占有大小为primarySize,高度为h,则存储记录公式为:
非叶结点计算主键数量: k e y s ∗ p r i m a r y S i z e + ( k e y s + 1 ) ∗ 6 = 16 ∗ 1024 keys*primarySize+(keys+1)*6=16*1024 keys∗primarySize+(keys+1)∗6=16∗1024
叶结点计算可以存储多少记录: k e y s h − 1 ⋅ 16 ∗ 1024 r o w S i z e = r e c o r d s \quad keys^{h-1}\cdot\frac{16*1024}{rowSize}=records keysh−1⋅rowSize16∗1024=records
如果小伙伴什么问题或者指教,欢迎交流。
❓QQ:806797785
参考链接:
[1]ChatGPT
[2]MySQL数据库视频[CP/OL].2020-04-16.p66-73.
[3]MySQL相关(番外篇)- innodb 逻辑存储结构.[CP/OL].
[4]MySQL之InnoDB存储引擎-逻辑存储结构.[CP/OL].