MySQL聚合索引与非聚合索引 "聚合索引(ClusteredIndex)"

聚集索引

聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个聚集索引,因为一个表的物理顺序只有一种情况,所以,对应的聚集索引只能有一个。

类似字典的拼音目录。表中的数据按照聚集索引的规则来存储的。就像新华字典。整本字典是按照A-Z的顺序来排列。这也是一个表只能有一个聚集索引的原因。因为这个特点,具体索引应该建在那些经常需要order by,group by,按范围取值的列上。因为数据本身就是按照聚集索引的顺序存储的。不应该建在需要频繁修改的列上,因为聚集索引的每次改动都以为这表中数据的物理数据的一次重新排序。就想新华字典一样。聚集索引适合建立在大数据量但是小数目不同值的列上,就像新华字典有收录了一两万的汉字,但是其拼音只有A-Z一样。但是并不是不同值越少越好。如果一个列只有极少值,如性别只有男女,在大数据量下无论是聚集索引和非聚集索引都是不适合建立的。因为其不同值辣么少。就像要查性别为男的,那么平均有一半就符合条件。就算建立索引也用处不大。值得注意的是有些数据库如sql server在你创建主键时会默认主键即为聚集索引,如果没有指定主键数据库本身也会创建一个不可见的索引,因为表本身总要有个排序规则是吧。主键作为聚集索引与大数据量但是小数目不同值适合建立聚集索引的规则是相违背的。即使这样也需要这样做的原因刚才说过,表总是需要一个排序规则的。如果你有更加合适的列适合做聚集索引是可以修改聚集索引的,但是聚集索引的修改一定一定一定要谨慎,因为聚集索引涉及要数据的物理存放数据。不合理的聚集索引会十分严重的拖累数据库的性能。

注意,虽然一般主键默认就是聚集索引,但是并不代表聚集索引的值具有唯一约束,主键不等于具体索引。这个不要弄混,刚才说过聚集索引适合大数据量但是小数目不同值的列上,聚集索引值是允许重复的,就像新华字典一样,拼音A下面会有很多字。


非聚集索引

一种索引,该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。

优劣势

优点

1.可以把相关数据保存在一起,如:实现电子邮箱时,可以根据用户ID来聚集数据,这样只需要从磁盘读取少量的数据页就能获取某个用户全部邮件,如果没有使用聚集索引,则每封邮件都可能导致一次磁盘IO

2.数据访问更快,聚集索引将索引和数据保存在同一个btree中,因此从聚集索引中获取数据通常比在非聚集索引中查找要快

3.使用覆盖索引扫描的查询可以直接使用页节点中的主键值

缺点

1.聚簇数据最大限度地提高了IO密集型应用的性能,但如果数据全部放在内存中,则访问的顺序就没有那么重要了,聚集索引也没有什么优势了

2.插入速度严重依赖于插入顺序,按照主键的顺序插入是加载数据到innodb表中速度最快的方式,但如果不是按照主键顺序加载数据,那么在加载完成后最好使用1optimize table`命令重新组织一下表

3.更新聚集索引列的代价很高,因为会强制innodb将每个被更新的行移动到新的位置

4.基于聚集索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临页分裂的问题,当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次页分裂操作,页分裂会导致表占用更多的磁盘空间

innodb和myisam物理存储的数据分布对比

myisam:

是按照数据插入的顺序存储在磁盘上的,myisam中的主键索引和二级索引在结构上并没有什么不同,主键索引就是一个名为primary的唯一非空索引。

innodb:

因为innodb支持聚集索引,所以使用非常不同的方式存储同样的数据,innodb聚集索引包含了整个表的数据,而不是只有索引,因为在Innodb中,聚集索引就是表,所以不像myisam那样需要独立的行存储。聚集索引的每一个叶子节点都包含了主键值,事务ID,用于事务和MVCC的回滚指针以及所有剩余列的值,如果主键是一个列前缀索引,innodb也会包含完整的主键列和剩下的列的值。

还有一点和myisam不同的是,innodb的二级索引和聚集索引很不同,innodb二级索引的叶子节点中存储的不是行指针,而是主键值,并以此作为指向行的指针,这样的策略减少了当出现行移动或者数据页的分裂时二级索引的维护工作,使用主键值当做指针会让二级索引占用更多的空间,换来的好处是,innodb在移动行时无须更新二级索引中的这个指针。

何时使用聚集索引或非聚集索引

MySQL聚合索引与非聚合索引

总结:

聚集索引就字典的首字母查询

非聚集索引就是字典的边盘部首查询

聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个

聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续


你可能感兴趣的:(MySQL聚合索引与非聚合索引 "聚合索引(ClusteredIndex)")