总结
   
    聚簇索引也叫
    
     聚集索引
    
    。,并不是一种单独的索引类型,而是一种数据存储方式。那么可以理解聚簇索引是一种抽象概念,在具体实现的时候,
    
     需要区分不同的引擎
    
    ,不同的引擎,实现细节有所不同。
   
不同的引擎有不同的实现, 很多文章忽略了区分引擎,因此让人很迷惑。
    
     那么什么是聚簇索引?
    
    
    
     聚簇索引的叶子节点就是数据节点,也就是说索引和数据行在一起;反之,如果叶子节点没有存储数据行,那么就是非聚簇索引。
    
   
    
     二级索引,又称作辅助索引,均属于非聚簇索引
    
   
如果反过来说,非聚簇索引就是二级索引,这种说法完全就是错误的。就像学生是人,但是人是学生就不对。
    在mysql数据库中,myisam引擎和innodb引擎使用的索引类型不同,
    
     myisam对应的是非聚簇索引
    
    ,而
    
     innodb对应的是聚簇索引
    
    。
   
    
    
    1. 聚簇索引
   
    《高性能MySQL》上说聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。那么mysql有哪些索引类型呢,参见
    
     《Mysql目前主要的几种索引类型》
    
   
例如,某个冒泡排序算法,对应这里的存储方式,是排序的算法的一种概念,你可以用java写出这个算法,也可以用c写出这个算法,具体语言,对应这里的索引类型。
聚簇索引的叶子节点就是数据节点,也就是说索引和数据行在一起。
    那么采用聚簇索引架构的innodb来说,他的叶子节点和数据行就是在一起的。我们来看下innodb B+树的实现:
    
    
    
    
     一个表只能有一个聚簇索引。
    
   
我们知道聚簇索引中包含了数据行,那么如果有多个聚簇索引,就说明存储了多份相同的数据行,岂不浪费空间?
    联想
    
     innodb
    
    的存储文件,在一个数据table中,它的
    
     数据文件和索引文件是同一个文件
    
    。即在查询过程中,
    
     找到了索引,便找到了数据文件
    
    。这也间接说明
    
     innodb
    
    采用的是聚簇索引。
   
聚簇索引默认由主键实现(用主键作为B+树的key,并且把数据行绑定在叶子节点)。
    如果表中没有定义主键A,InnoDB 会选择一个
    
     唯一且非空的列
    
    B代替(主键A的特性就是唯一且非空,如果把主键A比作嫡长子,那么列B就是其他儿子,只是继承的顺序靠后,但毕竟也是有皇家血脉的,没有嫡长子,就拿其他儿子当继承人了)。
   
    如果没有这样的列B,InnoDB 会
    
     隐式定义一个主键
    
    (类似oracle中的RowId)来作为聚簇索引。
   
    
     如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。
    
   
    
    
    一个坑
   
在一篇文章中有如下介绍,说法是不准确的:
“在《数据库原理》一书中是这么解释聚簇索引和非聚簇索引的区别的:
聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的
指针
。
”
我们知道聚簇索引是一个概念,那么非聚簇索引自然也是一个概念,需要明确指出的是InnoDB和myisam均用到非聚簇索引,但是他们有不同的实现。
    因此上面引用的话中,对非聚簇索引的描述”
    
     只不过有指向对应数据块的
     
      指针
     
    
    ”,特指myisam的非聚簇索引实现,而对于innodb的非聚簇索引实现,data指向的是主键值(通过主键值,去聚簇索引进行索引操作,找到叶子节点,数据在该叶子节点上,这个过程好像叫
    
     回表
    
    ),不是数据行,也不是指针。
   
当初没明白这些道理时,被搞的要吐血了
    
    
    2. 非聚簇索引
   
由前文知道,myisam采用非聚簇索引实现,那么我们来看下具体是怎么实现的。
    在myisam中,一个数据表table的存储文件,它是由
    
     table.frm、table.myd
    
    以及
    
     table.myi
    
    组成。table.myd记录了数据(数据行),table.myi记录了索引的数据。
   
myisam引擎的索引文件和数据文件是独立分开的,正好符合非聚簇索引的架构。
MyISM使用的是非聚簇索引,
非聚簇索引和InnoDB的聚簇索引这两棵B+树看上去没什么不同
,节点的结构完全一致,只是存储的内容不同而已,InnoDB主键聚簇索引B+树的节点存储了
主键和数据行
,MyISM非聚簇索引B+树存储了
主键和指向data的指针
。
     
   
    
    
    3. 二级索引
   
二级索引,又被称为辅助索引,在不同存储引擎中的内容不同。
    
     InnoDB
    
    中的
    
     二级索引
    
    存放的是
    
     主键值
    
    ,如果需要查询对应的数据行,需要
    
     回表查询
    
    ,即在聚簇索引中进一步查找对应的数据行。这样可以避免在行移动或者插入新数据时出现的页分裂问题。
   
InnoDB的二级索引更详细信息,可以参见
《InnoDB二级索引(辅助索引)》
    
     MyISAM
    
    中
    
     无论是主键索引还是二级索引
    
    ,
    
     索引的叶子节点存放的都是指向数据行的指针
    
    ,保证可以通过索引进而查找到对应的数据行,只需要对索引进行一遍查找。这样会存在页分裂问题。
   
    参考:
    
    
     《聚簇索引和非聚簇索引的区别》
    
    开篇定义聚簇索引那句话
   
    
     《Mysql聚簇索引和非聚簇索引》
    
    参考主体,但“聚簇索引也叫复合索引”描述是错误的
   
    
     《MySQL-聚簇索引》
    
    《高性能MySQ》一书的笔记
   
    
     《mysql聚簇索引详解》
    
    好像也是《高性能MySQ》的笔记
   
    
     《聚簇索引与非聚簇索引(也叫二级索引)》
    
    
    
     《mysql——二级索引(辅助索引)》
    
    二级索引作用
    
    
     《MySQL在Innodb和MyISAM中的二级索引》
    
   
 
