如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里
因为数据库索引的知识点比较多,而且感觉比较复杂和混乱!所以为了让文章更加的清晰,最终在按原目录结构写了三分之二的时候,还是决定分为两个部分分开去描述(虽然还是有很多地方没有去解释)
在学习MySQL的索引之前,我们很有必要先知道一个数据结构知识。
可以说,如果不知道这三个数据结构的情况下,硬啃MySQL索引是很吃力的,也不好理解。
因为一篇博客的篇幅有限,我也不想写成两三万字的大长文,所以有需要的朋友,可以从上面的子链看看这三个数据结点的简介和概念再回到本文继续浏览
毕竟B类树是构造MySQL数据库索引的底层实现(准确的说是B+树
),所以本文还是要略带的介绍一下的。
什么是B树?
B树,又名B-树(B减树
)。它是一棵多路平衡多路查找树。它具有一些索引结构的特性
总之,使用B树作为索引的存储结构,可以大幅的降低树的高度,保持一棵"矮胖树"
的特性, 降低磁盘IO操作,提高数据库查询性能
什么是B+树?
那什么是一棵B+树呢?B+树说白了就是B树的变种,也是一棵平衡多路查找树,但分别结合了B树和索引顺序访问的优势,更适合成为数据库索引的底层实现
总而言之就是,B+树综合了B树的优点,还带有顺序索引的功能,更加的牛逼
B+树为什么替换了B树称为MySQL索引的底层实现?
B+树的磁盘读写代价更低
B+树的查询效率更加稳定
B+树更有利对数据的扫描
范围查询
如果想要知道数据库索引的底层实现是怎么从二叉搜索树->平衡二叉搜索树->B树->B+树
的演进过程的也可以看这篇文章初入数据结构中的B类树(B Tree , B+ Tree)
(一)主键索引(Primary Index)
主键索引
(primary index
)主索引
primary key
)创建的索引树,我们就称其为该表的主键索引
(二)辅助键索引(Secondary Index)
辅助键索引
(secondary index
)辅助索引
,次级索引
,二级索引
辅助键索引
简而言之,如果将一张表的所有字段都单独建立一个索引,那么除了以主键生成的索引外,其他都属于辅助键索引。 其实辅助键索引更常叫辅助索引,只是我为了对应主键索引,还是叫辅助键索引能更让人容易理解,不容易混乱。
聚簇 - @百度百科
- 聚簇是为了提高某个属性(或属性组)的查询速度,把这个或这些属性(称为聚簇码)上具有相同值的元组集中存放在连续的物理块。
(一)聚簇索引(Clustered Index)
什么是聚簇索引?
聚集索引
。我们将根据键值对数据库表中的数据进行排序存储,并将相关的信息聚簇在一起索引就叫聚簇索引(该顺序是物理上连续的存储空间的顺序)聚簇索引的特性
聚簇索引定义了数据存储在表中的顺序,该表的数据有且仅以一种方式排序。因此,每个表只能有一个聚簇索引。在RDBMS中,在存在主键的情况下,主键索引就是该聚簇索引
聚簇索引其中一个大特征就是将索引和数据存储在同一个文件中,既叶子结点不仅保存键的信息,还保存了位于同一行其他列的信息,简而言之,聚簇索引的叶子结点保存的是一个完整行记录数据
同时我们也能知道聚簇索引是一种有序索引,它的具体实现可以是稠密索引,也可以是稀疏索引
GEN_CLUST_INDEX
隐式聚簇索引。该索引是基于一个名为DB_ROW_ID
的隐藏字段,通常称之隐式主键。为什么InnoDB存储引擎一定要有聚簇索引呢?
(二)非聚簇索引(Non- Clustered Index)
什么是非聚簇索引?
非聚簇索引的特征
MyISAM
)或是其主键信息(InnoDB
)。那些索引属于非聚簇索引
引用至:
@difference between sparse index and dense index - @stackoverflow
@Indexing in Databases | Set 1 - @GeeksForGeeks
Ordered Indexing is of two types:
- Dense Index
- Sparse Index
.
Dense Index :
An index record appears for every search key value in file.
This record contains search key value and a pointer to the actual record.
.
Sparse Index :
- Index records are created only for some of the records.
- To locate a record, we find the index record with the largest search key value less than or equal to the search key value we are looking for.
- We start at that record pointed to by the index record, and proceed along the pointers in the file (that is, sequentially) until we find the desired record.
说白了,稠密索引和稀疏索引属于有序索引(ordered index)
的一个分类
稠密索引:
稀疏索引:
1003
的数据,就要先找到小于或等于1003
的键,比如1001
。1001
的索引,我们找到1001
所在的行数据,然后线性向下遍历两次,我们就找到了1003
所在的行数据啦!稠密索引和稀疏索引的优缺点
Clustered index is dense or sparse?
覆盖索引(covering index
),也称为索引覆盖。其实我更想称其为索引覆盖,以为我理解的覆盖更像是一个动词。因为覆盖索引其实并不是一种索引类型,而是一个技术性的提升查询效率的机制。
什么是覆盖索引?
举个应用覆盖索引的粟子!
在InnoDB存储引擎的表中:
(col1,col2,col3)
,由三个列组成。那么我们的select col1,col2,col3 from table where col1 = xxx;
语句肯定会有覆盖索引的技术加持。只进行了一次(col1,col2,col3)
辅助键索引,我们就可以得到(col1,col2,col3)
三列数据的结果,自然也就不需要再拿到相关数据的主键,再跑到聚簇索引二次查询select col1 from table where col1 = xxx;
, 也会得到覆盖索引的技术加持。(一) 样例表
create table `student_innodb` (
`sid` int(11) not
null
,
`name` varchar(20) not
null
,
`age` int(11) not
null
,
`tel` varchar(11) not
null
,
`email` varchar(20) not
null
,
`class` varchar(20) not
null
,
primary key (`sid`),
unique name(`name`),
index
age(`age`),
index
tel_email(`tel`,`email`)
) engine=innodb default charset=utf8;
(二) InnoDB的表数据存放在哪?
我们知道,MySQL下的索引根据以列属性进行分类,可以分为主键索引
和辅助键索引
。在InnoDB下,主键索引采用的是聚簇索引,辅助键索引采用的是非聚簇索引。
InnoDB的数据实际存储在哪?
(三) InnoDB下利用索引查询的过程
下图为InnoDB下的走索引查询的过程
主键查询
select * from student_innodb where sid = 1;
其他字段索引的查询
select * from student_innodb where name = 'jerry';
name = 'jerry'
的行记录的主键信息sid = 1
sid = 1
的主键信息去主键索引中再次遍历,从根结点开始,直接叶子结点,便得到了行数据本身所以,我们知道在InnoDB中,查询条件是主键的索引查询,只需要遍历一次索引树,而非主键的条件,这需要两次,先遍历辅助键索引得到对应的主键信息,再通过主键信息在主键索引中遍历,得到行数据
(一) 样例表
create table `student_myisam` (
`sid` int(11) not
null
,
`name` varchar(20) not
null
,
`age` int(11) not
null
,
`tel` varchar(11) not
null
,
`email` varchar(20) not
null
,
`class` varchar(20) not
null
,
primary key (`sid`),
unique name(`name`),
index
age(`age`),
index
tel_email(`tel`,`email`)
) engine=myisam default charset=utf8;
(二) MyISAM的表数据存放在哪?
我们知道,MySQL下的索引根据以列属性进行分类,可以分为主键索引
和辅助键索引
。在MyISAM下,主键索引和辅助键索引都属于非聚簇索引。
MyISAM的数据实际存储在哪?
(三) MyISAM下利用索引查询的过程
select * from student_innodb where sid = 1;
通过其他非主键字段查询:
select * from student_innodb where name = 'jerry';
所以,我们知道在MyISAM中,查询不管是走主键索引,还是非主键索引,在叶子结点得到的都是目的数据的地址,还需要通过该地址,才能在数据文件中找到目的数据(只需要一次遍历和一次的地址访问)
(一) InnoDB的数据文件
我们创建一个名为student_innodb
的表,存储引擎使用InnoDB, 然后在搜索电脑中存放student_innodb
表数据文件的地方
可以看到两个文件,student_innodb.frm
和student_innodb.ibd
。熟悉的人肯定知道,这两个文件就是student_innodb表的表定义文件和数据文件
student_innodb.frm
student_innodb
表是一张怎么样的表student_innodb.ibd
总之,我们可以知道,InnoDB的表,数据存储文件只有一个,既.ibd
文件
(二) MyISAM的数据文件
我们创建一个名为student_myisam
的表,存储引擎使用MyISAM, 然后在搜索电脑中存放student_myisam
表数据文件的地方
我们可以看到三个文件, student_myisam.frm
, student_myisam.MYD
和student_myisam.MYI
文件。上面我们分析过了。.frm
文件是表定义文件,不是数据文件。所以我们只关注MYD和MYI结尾的文件。
student_myisam.MYD
.MYD
文件是MyISAM存储引擎表的所有行数据的文件student_myisam.MYI
.MYI
文件存放的是MyISAM存储引擎表的索引相关数据的文件总之,我们可以简单的得出结论,MyISAM引擎下,表数据和表索引数据是分开存储的。
(三) 总结
InnoDB,MyISAM B+Tree索引模型的区别和优缺点对比,在广义上的角度,问题可以切换成聚簇索引和非聚簇索引的优缺点对比。因为InnoDB和MyISAM的B+Tree索引机制,很大程度上的区别,就是一个支持聚簇索引,一个不支持
(一) 聚簇索引的优缺点
聚簇索引的优点
MAX, MIN, COUNT
等聚集函数都有很好的作用。聚簇索引的缺点
(二) 非聚簇索引的优缺点
非聚簇索引的优点
非聚簇索引的缺点
我知道很多情况下,有的朋友在看了一些书籍或博客之后,会有一种认知倾向,认为InnoDB的索引采用的就是聚簇索引,而MyISAM的索引采用的是非聚簇索引的方式。虽然可以这么说,但其实这个概念也并非完全正确。
所以总的来说,在广义上,通俗的角度来说,的确可以说InnoDB采用的是聚簇索引,MyISAM采用的是非聚簇索引。但更准确的说法是,InnoDB支持聚簇索引,MyISAM不支持聚簇索引
针对此文,最好可以看看官网对Clusered Index
和 Secondary Index
的解释@Clustered and Secondary Indexes - @MySQL 官网
MySQL支持哈希索引,但是局限于部分的存储引擎,既MEMORY/HEAP和NDB。而常见的InnoDB和MyISAM则并不支持。
什么是自适应哈希索引?
至此,我们可以知道InnoDB并不支持我们自建哈希索引,但是在某些情况下哈希索引的效率的确很高,于是InnoDB自己就为热点数据维护一套哈希索引,因为这套哈希索引并不是为所有数据建立的,而是由InnoDB动态监控,自行维护的,为部分热点数据优化速度而生。所以又名自适应哈希索引,以示区别。既自适应哈希索引是存储引擎自身的优化手段,并非提供出来给用户使用的索引类型。
引用至InnoDB关键特性之自适应hash索引
相比B+Tree索引,哈希索引有什么缺陷?
我们知道MySQL的InnoDB曾经是不支持MyISAM所独有的全文索引的。但是MySQL 5.6之后,InnoDB也支持全文索引FULLTEXT
了。
为什么叫倒排索引?
什么是倒排索引(Inverted index)?
说实话,倒排索引也不是一个简单的概念,很多搜索引擎的底层原理都是倒排索引,比如ElasticSearch等。
学习倒排索引的时候,最好还是需要一些搜索引擎的知识会更容易理解。
倒排索引就是相对正排索引相反而言的模型。正排索引是通过文档ID来遍历文档内容,找到关键字(文档 -> 关键字)。而倒排索引则是通过关键字,找到所在的文档(关键字 -> 文档)
以上正排索引,假如我们的搜索引擎是基于正排索引实现的,那么我们要在索引库中查询"python"
关键字, 就很可能需要一个一个文档的进行遍历,直到在某个文档的内容中找到"python"
单词。这样的一个时间复杂度是很大的,尤其是数据量很大的情况下。所以基于正排索引实现的搜索引擎是不现实的
如果在每一文档录入搜索引擎索引库的时候,我们就对文档的内容进行分词,统计,分析。建立倒排索引,记录分词得到的每个单词对应文档的出现位置和出现次数。 那么我们在搜索引擎查询"python"
关键字,就会非常的快速,只需要通过关键字就可以马上查询到已经预处理的统计分析结果。也就知道了'python'
关键字在文档A和文档B出现过。展示给用户即可。
这也是为什么是正排和倒排的原因,正排是通过文档查找关键字,倒排是通过关键字查到对应的文档。详细的倒排索引知识以后有时间再在ES的知识点中重点说明。
什么是倒排索引? - @作者:返回主页 大数据和人工智能躺过的坑
倒排索引为什么叫倒排索引?- @知乎
说实话呀,索引的概念就跟数据库的锁概念一样,四处充斥着各种各样的说法,各种各样的名词。对于初学者来说,十分的混淆。反正我整理本文时的心情是非常复杂的,所以我不能绝对的说,我表达的观点一定是正确的,但我努力让它是正确的。针对这样混乱的现象,我个人的感受是:
以上只是我的个人感受,如果因为是我的自身局限性导致将正确的结果误以为是一种混乱,希望大家告知!万分感谢
为了避免概念的混淆,我将自己认为是正确的说法,描述一下,大致从三个方向进行分类
这里对数据库的各类索引解释的比较齐全
(一)数据索引底层实现原理
B树索引
B+树索引
BitMap索引
Hash索引
(二)数据库支持的功能性索引
单列索引:
主键索引
唯一索引
普通索引
全文索引
多列索引:
组合索引
(三)数据库索引的内部实现的概念
主辅区分:
主键索引
(primary index
)主索引
primary key
)创建的索引树,我们就称其为该表的主键索引
辅助键索引
(secondary index
)辅助索引
,次级索引
,二级索引
辅助键索引
聚簇区分:
聚簇索引
(clustered index
)聚集索引
。针对MySQL而言,聚簇索引只存在于InnoDB中,再具体些,指代的就是InnoDB每个表的主键索引非聚簇索引
(non-clustered index
)稠密区分:
准确的说,是 有序索引
(ordered Index
)可以分为稠密索引和稀疏索引两类
稠密索引
(dense index
)密集索引
。稠密索引是指会为每一个数据都建立一个索引稀疏索引
(sparse index
)(四)总结一下
辅助键索引(Secondary Index)
通常称为辅助索引,有时也称为二级索引,次级索引主键索引(Primay Index)
在InnoDB引擎下,有时候它与聚簇索引(Clusered Index)
是等价的。主键索引(Primay Index)
和聚簇索引(Clusered Index)
等价的情况下,例如InnoDB, 与主键索引(聚簇索引)相对的辅助键索引(辅助索引(Secondary Index)
)就是非聚簇索引(Non-Clusered Index)
Clusered Index
)在InnoDB下又是一种有序索引(Ordered Index
),所以聚簇索引又可以有具体的采用形式,可以是稠密索引形式(Dense Index
),也可以是稀疏索引形式(Sparse Index
)。总而言之,中文博大精深,名词多样化,如果要得知一个名词最精确的含义,建议还是得知道它的英文名词。这一点在数据库索引具体实现内部分类
的名词中最容易产生混淆,切记切记。然后根据不同的角度,又可以得到很多的分类,有些概念的边界也的确很难找,我也不想深究了,毕竟都快咬文嚼字了,这种感觉烦的很。
《MySQL技术内幕》
深入理解MySQL索引原理和实现——为什么索引可以加速查询?
mysql在innodb索引下b+树的高度问题 - @作者: 面壁偷笑
InnoDB一棵B+树可以存放多少行数据?- @作者: 李平
Mysql聚簇索引和非聚簇索引原理(数据库) - @作者:小楼东风细雨
difference between sparse index and dense index - @stackoverflow
Indexing in Databases | Set 1 - @GeeksForGeeks
DBMS - Indexing - @tutorials-point
聚集索引 非聚集索引 聚簇索引 稀疏索引 稠密索引 - @作者:douunderstand
Clustered vs Non-clustered Index: Key Differences with Example - @guru99 (推荐!!)
如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!