【MySQL】汇集索引和非汇集索引

never too late~sql

    索引(在MySQL中也叫作“键(key)”) 是存储引擎用于快速找到记录的一种数据结构。这是索引的基本功能。数据库

    索引对于良好的性能很是关键。尤为是当表中的数据量愈来愈大时,索引对性能的影响跃愈发重要。在数据量较小且负载较低时,不恰当的索引对性能的影响可能还不明显,可是当数据量逐渐增大时,性能则会急剧降低。数据结构

1、索引基础性能

Q1:索引是如何工做的?优化

A1:要理解MySQL中索引是如何工做的,最简单是方法就是区看一看一本书的目录。假若想在一本书中找到某个特定命题,通常会先看书的“索引”,找到对应的页码。url

    那么在MySQL中,存储引擎的用相似的方法使用索引,它先在索引中找到对应值,而后根据匹配的索引记录找到对应的数据行。spa

 

Q2:MySQL支持的索引的类型?以及优缺点.net

A2:B-Tree 索引、哈希索引、空间数据索引、全文索引等其余索引。指针

  • B-Tree一般意味着全部的值都是按顺序存储的,而且每个叶子页到跟的距离相同。叶子页比较特殊,它的指针指向的是被索引的数据,而不是其余的节点页。

图1 B-Tree (从技术上来讲是B+tree)索引树种的部分条目示例code

回想BTree的查找操做:进行查找操做时,首先在根节点进行二分查找,找到一个 key 所在的指针,而后递归地在指针所指向的节点进行查 找。直到查找到叶子节点,而后在叶子节点上进行二分查找,找出 key 所对应的 data
这也就意味着B-Tree索引可以加快数据的访问速度,由于存储引擎再也不须要进行全表扫描来获取须要的数据,取而代之的是从索引的根节点开始进行搜索。根节点的槽中存放了指向子节点的指针,存储引擎很具这些指针向下层查找。经过比较节点页的值和要查找的值能够找到合适的指针进入下层子节点,这些指针实际上定义了节点页中的上限和下限。
 
那么有哪些可使用B-Tree索引的查询类型:
(1)全值匹配:
(2)匹配最左前缀
(3)匹配列前缀
(4)匹配范围值
(5)精确匹配某一列并范围匹配另一列
(6)只范围跟索引的查询
 
除了上述适用以外,它也存在局限性:
(1)若是不是按照索引的最左列开始查找,那么没法使用索引
(2)不能跳过索引中的列
(3)若是查询中又某个列的范围查询,则其右边全部列都没法使用索引优化查询。

 

  • 哈希索引基于哈希表实现,只有精确匹配索引全部列的查询才有效。对于每一行数据,存储引擎都会对全部的索引列计算一个哈希码。哈希索引将全部的哈希码存储在索引中,同时在哈希表中保存指向每一个数据行的指针。

限制之处:

(1)哈希索引只包含哈希值和行指针,而不存储字段值。

(2)哈希索引数据不是按照索引值的顺序排序的,因此没法用于排序。

(3)不支持部分索引列匹配查找。

(4)只支持等值比较查询

(5)哈希冲突多的话,索引维护操做的代价也会很高。

  • 空间数据索引(R-Tree)

MyISAM 表支持空间索引,能够用做地理数据存储。这类索引无须前缀查询。空间索引会从全部维度来索引数据。这一类型索引,接触的不多,之后碰到再作详细总结。

  • 全文索引,这是一种特殊类型的索引,它查找的是文本中的关键词。将来遇到了再总结。

 

2、汇集索引和非汇集索引

汇集索引和非汇集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

一、汇集索引

汇集索引表记录的排列顺序和索引的排列顺序一致(以InnoDB汇集索引的主键索引来讲,叶子节点中存储的就是行数据,行数据在物理储器中的真实地址就是按照主键索引树造成的顺序进行排列的),因此查询效率快,只要找到第一个索引值记录,其他就连续性的记录在物理也同样连续存放。汇集索引对应的缺点就是修改慢,由于为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页从新排序(由于在真实物理存储器的存储顺序只能有一种,而插入新数据必然会致使主键索引树的变化,主键索引树的顺序发生了改变,叶子节点中存储的行数据也要随之进行改变,就会发生大量的数据移动操做,因此效率会慢)。由于在物理内存中的顺序只能有一种,因此汇集索引在一个表中只能有一个

二、非汇集索引

非汇集索引制定了表中记录的逻辑顺序,可是记录的物理和索引不必定一致(在逻辑上数据是按顺序排存放的,可是物理上在真实的存储器中是散列存放的),两种索引都采用B+树结构,非汇集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非汇集索引层次多,不会形成数据重排。因此若是表的读操做远远多于写操做,那么就可使用非汇集索引。

三、对比两种索引的例子

汇集索引就相似新华字典中的拼音排序索引,都是按顺序进行,例如找到字典中的“爱”,就里面顺序执行找到“癌”。而非汇集索引则相似于笔画排序,索引顺序和物理顺序并非按顺序存放的。总的来讲,汇集索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块

索引建立Demo

CREATE DATABASE `IndexDemo`
go 
USE `IndexDemo`
go 
CREATE TABLE `ABC` 
( 
`A` INT NOT NULL, 
`B` CHAR(10), 
`C` VARCHAR(10) 
) 
go 
INSERT INTO `ABC` SELECT 1,'B','C' 
UNION SELECT 5,'B','C' 
UNION SELECT 7,'B','C' 
UNION SELECT 9,'B','C' 
go 
SELECT * FROM abc

这个时候插入一条数据,

INSERT INTO `abc` VALUES('6','B','C')

此时的查询记录以下:

添加汇集索引,再查询数据显示则以下,此时发现表的顺序发生了变化,此时的排序按A字段的递增排序。这就说明了使用汇集索引若是插入新数据会进行从新排序

四、汇集索引和非汇集索引的区别总结:

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

五、其余问题

咱们须要搞清楚如下几个问题:

  第一:汇集索引的约束是惟一性,是否要求字段也是惟一的呢?     不要求惟一!

  分析:若是认为是的朋友,多是受系统默认设置的影响,通常咱们指定一个表的主键,若是这个表以前没有汇集索引,同时创建主键时候没有强制指定使用非汇集索引,SQL会默认在此字段上建立一个汇集索引,而主键都是惟一的,因此理所固然的认为建立汇集索引的字段也须要惟一。

  结论:汇集索引能够建立在任何一列你想建立的字段上,这是从理论上讲,实际状况并不能随便指定,不然在性能上会是恶梦。

 

        第二:为何汇集索引能够建立在任何一列上,若是此表没有主键约束,即有可能存在重复行数据呢?

  粗一看,这还真是和汇集索引的约束相背,但实际状况真能够建立汇集索引。

  分析其缘由是:若是未使用 UNIQUE 属性建立汇集索引,数据库引擎将向表自动添加一个四字节 uniqueifier 列。必要时,数据库引擎 将向行自动添加一个 uniqueifier 值,使每一个键惟一。此列和列值供内部使用,用户不能查看或访问。

 

  第三:是否是汇集索引就必定要比非汇集索引性能优呢?

  若是想查询学分在60-90之间的学生的学分以及姓名,在学分上建立汇集索引是不是最优的呢?

  答:否。既然只输出两列,咱们能够在学分以及学生姓名上建立联合非汇集索引,此时的索引就造成了覆盖索引,即索引所存储的内容就是最终输出的数据,这种索引在比以学分为汇集索引作查询性能更好。就是说咱们用学分去创建非汇集索引,那么搜索出来以后结点中的索引数据区只存有学分的数据,还须要根据叶子节点中数据区中的地址去查询,可是若是直接将要查询的学分字段和姓名字段建立一个联合索引(也是非汇集索引),这样在索引树中查找到数据以后直接就能在节点的索引数据区取得两个索引值,就不用再经过叶子节点中数据区里面的地址再去查询一次了。

 

  第四:在MySQL数据库中经过什么描述汇集索引与非汇集索引的?

  索引是经过B+树的形式进行描述的,咱们能够这样区分汇集与非汇集索引的区别:InnoDB中的汇集索引的叶节点就是最终的数据节点,InnoDB中的非汇集索引叶子节点指向的是相应的主键值。而MyISAM中非汇集索引的主键索引树和二级索引树的叶节仍然是索引节点,但它有一个指向最终数据的指针。

 

  第五:在主键是建立汇集索引的表在数据插入上为何比主键上建立非汇集索引表速度要慢?

  汇集索引的缺点是对表进行修改速度较慢,这是为了保持表中的记录的物理顺序与索引的顺序一致,而把记录插入到数据页的相应位置,必须在数据页中进行数据重排,下降了执行速度。插入数据时速度要慢(时间花费在“物理存储的排序”上,也就是首先要找到位置而后插入)。非汇集索引指定了表中记录的逻辑顺序,但记录的物理顺序和索引的顺序不一致,汇集索引和非汇集索引都采用了B+树的结构,但非汇集索引的叶子层并不与实际的数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针的方式。非汇集索引比汇集索引层次多,添加记录不会引发数据顺序的重组。这就是为何主键上建立非汇集索引比主键上建立汇集索引在插入数据时要快的真正缘由。

 

参考文章:

【MySQL】MySQL的存储引擎和索引详解(汇集索引和非汇集索引)

《高性能MySQL》