MySQL聚簇索引和非聚簇索引

MySQL聚簇索引和非聚簇索引

    • 非聚簇索引
    • 聚簇索引
    • 两区的对比及区别
    • 聚簇索引的优势

可以说数据库必须有索引,没有索引则检索过程变成了顺序查找,O(n)的时间复杂度几乎是不能忍受的。我们非常容易想象出一个只有单关键字组成的表如何使用B+树进行索引,只要将关键字存储到树的节点即可。当数据库一条记录里包含多个字段时,一棵B+树就只能存储主键,如果检索的是非主键字段,则主键索引失去作用,又变成顺序查找了。这时应该在第二个要检索的列上建立第二套索引。 这个索引由独立的B+树来组织。有两种常见的方法可以解决多个B+树访问同一套表数据的问题,一种叫做聚簇索引(clustered index ),一种叫做非聚簇索引(secondary index)。这两个名字虽然都叫做索引,但这并不是一种单独的索引类型,而是一种数据存储方式。对于聚簇索引存储来说,行数据和主键B+树存储在一起,辅助键B+树只存储辅助键和主键,主键和非主键B+树几乎是两种类型的树。对于非聚簇索引存储来说,主键B+树在叶子节点存储指向真正数据行的指针,而非主键。

非聚簇索引

MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树

  1. 结构分析
    原始数据

    存储方式

    按照列值和行号来组织索引的 叶子节点中保存的实际上是指向存放数据块的指针
    从物理文件中也可以看出 MyISAM的索引文件.MYI和数据文件.MYD是分开存储的 是相对独立的
  2. mysql实例分析
    索引节点的叶子页面就好比一片叶子。叶子头便是索引键值。
    先创建一张表:
CREATE TABLE `user` ( 
`id` INT NOT NULL ,
`name` VARCHAR NOT NULL ,
`class` VARCHAR NOT NULL);

对于MYISAM引擎,如果创建 id 和 name 为索引。对于下面查询:

select * from user where id = 1

会利用索引,先在索引树中快速检索到 id,但是要想取到id对应行数据,必须找到改行数据在硬盘中的存储位置,因此MYISAM引擎的索引 叶子页面上不仅存储了主键id 还存储着 数据存储的地址信息。如图:
在这里插入图片描述
像这样的索引就称为非聚簇索引。
非聚簇索引的二级索引与主键索引类似。假设我们对name添加索引,那么name的索引树叶子将是如下结构:
在这里插入图片描述

聚簇索引

InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。

  1. 结构分析
    于InnoDB引擎来说,是按照聚簇索引的形式存储数据

    它的每个聚簇索引的叶子节点都包含主键值、事务ID、回滚指针(用于事务和MVCC)以及余下的列。
    从物理文件也可以看出 InnoDB的数据文件只有数据结构文件.frm和数据文件.idb 其中.idb中存放的是数据和索引信息 是存放在一起的

  2. mysql实例分析
    对于 非聚簇索引 来说,每次通过索引检索到所需行号后,还需要通过叶子上的磁盘地址去磁盘内取数据(回行)消耗时间。为了优化这部分回行取数据时间,InnoDB 引擎采用了聚簇索引。
    聚簇索引,即将数据存入索引叶子页面上。对于 InnoDB 引擎来说,叶子页面不再存该行对应的地址,而是直接存储数据:
    在这里插入图片描述
    这样便避免了回行操作所带来的时间消耗。 使得 InnoDB 在某些查询上比 MyISAM 还要快!
    在二级索引方面, InnoDB 与 MyISAM 有很大区别。
    InnoDB默认对主键建立聚簇索引。如果你不指定主键,InnoDB会用一个具有唯一且非空值的索引来代替。如果不存在这样的索引,InnoDB会定义一个隐藏的主键,然后对其建立聚簇索引。一般来说,InnoDB 会以聚簇索引的形式来存储实际的数据,它是其它二级索引的基础。
    假设对 InnoDB 引擎上表name字段加索引,那么name索引叶子页面则只会存储主键id:
    在这里插入图片描述
    检索时,先通过name索引树找到主索引id,再通过id在主索引树的聚簇索引叶子页面取出数据。

两区的对比及区别

为了更形象说明这两种索引的区别,我们假想一个表如下图存储了4行数据。其中Id作为主索引,Name作为辅助索引。图示清晰的显示了聚簇索引和非聚簇索引的差异。
在这里插入图片描述
在这里插入图片描述
从图中可以看出 InnoDB二级索引的叶子节点存放的是KEY字段+主键值,因此首先通过二级索引查找到的是主键值,再根据主键值在主建索引中查找到相应的数据文件。
而MyISAM的二级索引存放的还是列值和行号的组合 叶子节点中保存的是指向物理数据的指针,因此它的主建索引和二级索引的结构并没有任何区别,只是说主键索引的索引值是唯一且非空的,而MyISAM引擎可以不设置主键。
InnoDB引擎是必须设置主键的,需要依赖主键生成聚簇索引,因此当没有指定主键的时候,InnoDB引擎会默认寻找一个可以唯一标识每行数据的列作为主键,当这种列不存在的时候,会默认生成一个6字节整型的隐藏列作为主键

聚簇索引的优势

我们重点关注聚簇索引,看上去聚簇索引的效率明显要低于非聚簇索引,因为每次使用辅助索引检索都要经过两次B+树查找,这不是多此一举吗?聚簇索引的优势在哪?

  1. 由于行数据和叶子节点存储在一起,这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。
  2. 辅助索引使用主键作为"指针" 而不是使用地址值作为指针的好处是,减少了当出现行移动或者数据页分裂时辅助索引的维护工作,使用主键值当作指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"。也就是说行的位置会随着数据库里数据的修改而发生变化(前面的B+树节点分裂以及Page的分裂),使用聚簇索引就可以保证不管这个主键B+树的节点如何变化,辅助索引树都不受影响。
  3. 关于查询时间,一般认为 MyISAM 牺牲了功能换取了性能,查询更快。但事实并不一定如此。多数情况下,MyISAM 确实比 InnoDB 查的快 。但是查询时间受多方面因素影响。InnoDB 查询变慢得原因是因为支持事务、回滚等等,使得 InnoDB的叶子页面实际上还包含有事务id(换句话说就是版本号) 以及回滚指针。

添加链接描述
http://www.cnblogs.com/crazylqy/p/7615393.html
http://www.cnblogs.com/crazylqy/p/7615457.html
http://blog.51cto.com/2839840/2057806?utm_source=oschina-app

你可能感兴趣的:(SQL,聚簇索引,非聚簇索引)