MySQL中每一个表都有一个聚簇索引( clustered index ),除此以外的表上的每一个非聚簇索引都是二级索引,又叫辅助索引( secondary indexes )。以InnoDB来讲,每一个InnoDB表具备一个特殊的索引称为汇集索引。若是表上定义有主键,那么该主键索引是汇集索引。若是表中没有定义主键,那么MySQL取第一个惟一索引( unique )并且只含非空列( NOT NULL )做为主键,InnoDB使用它做为汇集索引。若是没有这样的列,InnoDB就本身产生一个这样的ID值,它有六个字节,并且是隐藏的,使其做为聚簇索引。html
0x01:聚簇索引,提及索引,不能不说B+树mysql
http://blog.codinglabs.org/articles/theory-of-mysql-index.html
MySQL官方索引的定义:索引( Index )是帮助MySQL高效获取数据的数据结构。提取句子主干,就能够获得索引的本质;索引是数据结构。算法
数据库查询是数据库的最主要功能之一。谁都但愿查询数据的速度能尽量的快,所以数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法固然是顺序查找( linear search ),这种复杂度为O(n)的算法在数据量很大时显然是糟糕的,好在计算机科学的发展提供了不少更优秀的查找算法,例如二分查找(binary search),二叉树查找(binary tree search)等。若是稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,可是数据自己的组织结构不可能彻底知足各类数据结构(例如,理论上不可能同时将两列都按顺序进行组织),因此在数据以外,数据库系统还维护着知足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就能够在这些数据结构上实现高级查找算法。这种数据结构,就是索引。sql
聚簇索引并非一种单独的索引类型,而是一种数据存储方式。具体的细节依赖于其实现方式,但InnoDB的聚簇索引实际上在同一个结构中保存了B-Tree索引和数据行。数据库
当表有聚簇索引时,他的数据行实际上存放在索引的叶子页(leaf page)中。术语 “聚簇”表示数据行和相邻的键值紧凑地存储在一块儿(这并不是总成立)。由于没法同时把数据行存放在两个不一样的地方,索引一个表只能有一个聚簇索引。数据结构
0x02:聚族索引的优势ide
能够把相关数据保存在一块儿。例如实现电子邮件时,能够根据用户ID来汇集数据,这样只须要从磁盘读取少数的数据页就能获取某个用户的所有邮件。若是没有使用聚族索引,则每封邮件均可能致使一次磁盘I/O;性能
数据访问更快。聚族索引将索引和数据保存在同一个B-Tree中,所以从聚族索引中获取数据一般比在非聚族索引中查找更快。优化
使用覆盖索引扫描的查询能够直接使用节点中的主键值。设计
0x03:聚族索引的缺点
聚簇数据最大限度的提升了I/O密集型应用的性能,但若是数据所有都放在内存中,则访问的顺序就没有那么重要了,聚簇索引也就没有那么优点了;
插入速度严重依赖于插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。但若是不是按照主键顺序加载数据,那么在加载完成后最好使用OPTIMIZE TABLE命令从新组织一下表。
更新聚簇索引列的代价很高,由于会强制InnoDB将每一个被更新的行移动到新的位置。
基于聚簇索引的表在插入新行,或者主键被更新致使须要移动行的时候,可能面临“页分裂”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次分裂操做。页分裂会致使表占用更多的磁盘空间。
聚簇索引可能致使全表扫描变慢,尤为是行比较稀疏,或者因为页分裂致使数据存储不连续的时候。
二级索引(非聚簇索引)可能比想象的要更大,由于在二级索引的叶子节点包含了引用行的主键列。
二级索引访问须要两次索引查找,而不是一次。
有关二级索引须要两次索引查找的问题?
答案在于二级索引中保存的“行指针”的实质。要记住,二级索引叶子节点保存的不是指向行的物理位置的指针,而是行的主键值。这意味着经过二级索引查找行,存储引擎须要找到二级索引的叶子节点得到对应的主键值,而后根据这个值去聚簇索引中查找到对应的行。这里作了重复的工做:两次B-Tree查找而不是一次。对于InnoDB,自适应哈希索引可以减小这样的重复工做。