Mysql - 聚集索引与非聚集索引的区别

按照物理实现方式,索引可以分为两大类:

1)聚集索引:在聚集索引里,表中数据行按索引的排序方式进行存储,对查找行很有效。只有当表包含聚集索引时,表内的数据行才会按找索引列的值在磁盘上进行物理排序和存储。每张表只能有一个聚集索引,原因很简单,因为数据行本身只能按一个顺序存储。

特点:

1.索引内容本身就是目录,您不需要再去查其他目录来找到您需要找的内容。
2.叶子节点上包含着该行的所有信息。当您找到该叶子节点的时候,不需要再回表,直接可以取出该行数据的所有信息。
3.每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。

举例:

聚集索引就好比只有正文(没有目录)的汉语字典一样。我们知道汉语字典的排列顺序是从字母“a”开头并以“z”结尾的。如果我们要找“安”这个字。那就需要找以字母‘a’开头的那部分内容,如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字。相反,如果您找到了这个字,那您就可以直接找到关于“安”字的所有信息。

2)非聚集索引:非聚集索引也称为二级索引或者辅助索引,对于非聚集索引,数据库会有单独的存储空间来存放。非聚集索引在查找的时候要经过两个步骤,需要先搜索非聚集索引的B+Tree,这个B+Tree的叶子结点存储的不是完整的数据行,而是主键值,当搜索完成后得到主键的值,然后拿着主键值再去搜索主键索引的B+Tree,就可以获取到一行完整的数据。

特点:

1.一张表的聚集索引个数可能有多个,最多可以创建249个非聚集索引。
2.先建聚集索引才能创建非聚集索引。
3.非聚集索引数据与索引不同序。
4.非聚集索引在叶节点上有一个“指针”直接指向要查询的数据区域。
5.需要两个过程:先找到目录中的结果,再翻到您所需要的页码。

举例:

非聚集索引用字典来打比方:当遇到你不知道怎么读的字,那么你就需要利用偏旁部首来查询字典,当您在目录上找到这个字后,根据目录后面显示的页码再去字典中找字。比如:我们要找“张字”,根据偏旁部首,我们在检字表中找到“张”的页码是672页,然后,再翻到672页查找“张”字的相关信息。

InnoDb:主键索引采用聚集索引,非主键索引是非聚集索引

MYISAM:均采用非聚集索引

通过聚集索引可以直接查询到一行的记录,不用回表查询;但通过普通索引(非聚集索引)需要扫描两遍索引树。(即如果在查询中用到了非聚集索引,那么就会搜索两棵 B+Tree,第一次搜索 B+Tree 拿到主键值后再去搜索聚集索引的 B+Tree,这个过程就是所谓的回表。)

例如:

对于非聚集索引,数据库会有单独的存储空间来存放。非聚集索引在查找的时候要经过两个步骤,执行 select * from user where username='goboy'(假设 username 字段是非聚集索引),那么此时需要先搜索 username 这一列索引的 B+Tree,这个 B+Tree 的叶子结点存储的不是完整的数据行,而是主键值,当搜索完成后得到主键的值,然后拿着主键值再去搜索主键索引的 B+Tree,就可以获取到一行完整的数据。

数据库索引可以按照两种思路来分类:

注意:主键索引是一种特殊的聚集索引,它是唯一的,并且在许多数据库管理系统中,主键索引是默认的聚集索引。在设计表结构时,应根据具体的需求选择合适的索引类型。如果需要快速查询和排序数据,则使用聚集索引;如果需要唯一标识表中的行,则使用主键索引。

聚集索引和非聚集索引的比较

1.查询数据的速度:聚集索引优于非聚集索引。
2.插入数据的速度:非聚集索引要比聚集索引要快。

1)聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。
2)聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续。
3)聚集索引:物理存储按照索引排序;聚集索引是一种索引组织形式,索引的键值逻辑顺序决定了表数据行的物理存储顺序。非聚集索引:物理存储不按照索引排序;非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序。
4)索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。

注意:与聚集索引不同,非聚集索引并不改变数据表的物理存储顺序,因此对于数据表的插入、删除和更新操作的影响较小。

例如:

建表(InnoDB)

create table test 
( 
A int not null, 
B char(10), 
C varchar(10) 
) ENGINE=InnoDB;

插入四条记录:

insert into test select 1,'B','C' 
union select 7,'B','C' 
union select 5,'B','C' 
union select 9,'B','C' 

查询:

1)聚集索引:

ALTER TABLE test ADD PRIMARY KEY (A); # 添加聚集索引

现在插入一条记录:

insert into test values('4','B','C')

查询:

结果:表的物理存储顺序被改变了。

2)非聚集索引(普通索引):

ALTER TABLE test ADD INDEX index_name (A); # 添加非聚集索引

现在插入一条记录:

insert into test values('4','B','C')

结果:表的物理存储顺序没有变化。

 

posted @ 2024-03-05 20:17  李若盛开  阅读(3984)  评论(1)    收藏  举报