聚簇索引与非聚簇索引(也叫二级索引)

  • 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
  • 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam经过key_buffer把索引先缓存到内存中,当须要访问数据时(经过索引访问数据),在内存中直接搜索索引,而后经过索引找到磁盘相应数据,这也就是为何索引不在key buffer命中时,速度慢的缘由

澄清一个概念:innodb中,在聚簇索引之上建立的索引称之为辅助索引,辅助索引访问数据老是须要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、惟一索引,辅助索引叶子节点存储的再也不是行的物理位置,而是主键值mysql

什么时候使用聚簇索引与非聚簇索引

cluster.png算法

聚簇索引具备惟一性

因为聚簇索引是将数据跟索引结构放到一块,所以一个表仅有一个聚簇索引sql

一个误区:把主键自动设为聚簇索引

聚簇索引默认是主键,若是表中没有定义主键,InnoDB 会选择一个惟一的非空索引代替。若是没有这样的索引,InnoDB 会隐式定义一个主键来做为聚簇索引。InnoDB 只汇集在同一个页面中的记录。包含相邻健值的页面可能相距甚远。若是你已经设置了主键为聚簇索引,必须先删除主键,而后添加咱们想要的聚簇索引,最后恢复设置主键便可数据库

此时其余索引只能被定义为非聚簇索引。这个是最大的误区。有的主键仍是无心义的自动增量字段,那样的话Clustered index对效率的帮助,彻底被浪费了。缓存

刚才说到了,聚簇索引性能最好并且具备惟一性,因此很是珍贵,必须慎重设置。通常要根据这个表最经常使用的SQL查询方式来进行选择,某个字段做为聚簇索引,或组合聚簇索引,这个要看实际状况。性能

记住咱们的最终目的就是在相同结果集状况下,尽量减小逻辑IO大数据

结合图再仔细点看

image优化

imagespa

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

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

聚簇索引的优点

看上去聚簇索引的效率明显要低于非聚簇索引,由于每次使用辅助索引检索都要通过两次B+树查找,这不是画蛇添足吗?聚簇索引的优点在哪?

  1. 因为行数据和叶子节点存储在一块儿,同一页中会有多条行数据,访问同一数据页不一样行记录时,已经把页加载到了Buffer中,再次访问的时候,会在内存中完成访问,没必要访问磁盘。这样主键和行数据是一块儿被载入内存的,找到叶子节点就能够马上将行数据返回了,若是按照主键Id来组织数据,得到数据更快
  2. 辅助索引使用主键做为"指针"而不是使用地址值做为指针的好处是,减小了当出现行移动或者数据页分裂时辅助索引的维护工做使用主键值看成指针会让辅助索引占用更多的空间,换来的好处是InnoDB在移动行时无须更新辅助索引中的这个"指针"也就是说行的位置(实现中经过16K的Page来定位)会随着数据库里数据的修改而发生变化(前面的B+树节点分裂以及Page的分裂),使用聚簇索引就能够保证无论这个主键B+树的节点如何变化,辅助索引树都不受影响
  3. 聚簇索引适合用在排序的场合,非聚簇索引不适合
  4. 取出必定范围数据的时候,使用用聚簇索引
  5. 二级索引须要两次索引查找,而不是一次才能取到数据,由于存储引擎第一次须要经过二级索引找到索引的叶子节点,从而找到数据的主键,而后在聚簇索引中用主键再次查找索引,再找到数据
  6. 能够把相关数据保存在一块儿。例如实现电子邮箱时,能够根据用户 ID 来汇集数据,这样只须要从磁盘读取少数的数据页就能获取某个用户的所有邮件。若是没有使用聚簇索引,则每封邮件均可能致使一次磁盘 I/O。

聚簇索引的劣势

  1. 维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page split)的时候。建议在大量插入新行后,选在负载较低的时间段,经过OPTIMIZE TABLE优化表,由于必须被移动的行数据可能形成碎片。使用独享表空间能够弱化碎片
  2. 表由于使用UUId(随机ID)做为主键,使数据存储稀疏,这就会出现聚簇索引有可能有比全表扫面更慢,

image

因此建议使用int的auto_increment做为主键

image

主键的值是顺序的,因此 InnoDB 把每一条记录都存储在上一条记录的后面。当达到页的最大填充因子时(InnoDB 默认的最大填充因子是页大小的 15/16,留出部分空间用于之后修改),下一条记录就会写入新的页中。一旦数据按照这种顺序的方式加载,主键页就会近似于被顺序的记录填满(二级索引页多是不同的)

  1. 若是主键比较大的话,那辅助索引将会变的更大,由于辅助索引的叶子存储的是主键值;过长的主键值,会致使非叶子节点占用占用更多的物理空间

为何主键一般建议使用自增id

聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据必定也是相邻地存放在磁盘上的。若是主键不是自增id,那么能够想 象,它会干些什么,不断地调整数据的物理地址、分页,固然也有其余一些措施来减小这些操做,但却没法完全避免。但,若是是自增的,那就简单了,它只须要一 页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

由于MyISAM的主索引并不是聚簇索引,那么他的数据的物理地址必然是凌乱的,拿到这些物理地址,按照合适的算法进行I/O读取,因而开始不停的寻道不停的旋转聚簇索引则只需一次I/O。(强烈的对比)

不过,若是涉及到大数据量的排序、全表扫描、count之类的操做的话,仍是MyISAM占优点些,由于索引所占空间小,这些操做是须要在内存中完成的

mysql中聚簇索引的设定

聚簇索引默认是主键,若是表中没有定义主键,InnoDB 会选择一个惟一的非空索引代替。若是没有这样的索引,InnoDB 会隐式定义一个主键来做为聚簇索引。InnoDB 只汇集在同一个页面中的记录。包含相邻健值的页面可能相距甚远。

相关文章
相关标签/搜索