这是我参与更文挑战的第7天,活动详情查看: 更文挑战
前言
本文介绍MySQL的聚簇索引。
聚簇索引的实质
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。InnoDB的聚簇索引实际上在同一个结构中保存了B-Tree索引和数据行。当表有聚簇索引时,它的数据行实际上存放在索引的叶子页中。“聚簇”表示数据行和相邻的键值紧凑的存储在一起。因为一个表的数据行只能存放在一个地方,所以一个表只能有一个聚簇索引。
聚簇索引的创建方式
InnoDB使用主键来聚集索引,如果没有主键,InnoDB会选择一个唯一的非空索引代替,如果还没有InnoDB会隐式定义一个主键GEN_CLUST_INDEX(6 byte)来作为聚簇索引,这一列会自动增长,有点像Auto-increment的感觉。
聚簇索引的优缺点
优点
查询更快。可以从磁盘读取更少的数据页。使用覆盖索引扫描的查询可以直接使用页节点中的主键值。
缺点
1.聚簇数据最大限度地提高了I/О密集型应用的性能,但如果数据全部都放在内存中,则访问的顺序就没那么重要了,聚簇索引也就没什么优势了。所以说内存越大越好,但是内存也不是无限的,所以数据全放内存中不现实!说到底,还是得做存储和内存之间的数据加载,那么聚簇索引就必不可少了。
2.插入速度严重依赖于插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。但如果不是按照主键顺序插入数据,那么在加载完成后最好使用OPTIMIZE TABLE命令重新组织一下表。 比如有的地方为了防止爬虫的按Id遍历爬取,使用UUID作为表的主键,这样是防住了爬虫,却为数据库带来了很大影响。
因为新行的主键值不一定比之前插入的大,所以InnoDB无法简单地总是把新行插入到索引的最后,而是需要为新的行寻找合适的位置--—通常是已有数据的中间位置——并且分配空间。这会增加很多的额外工作,并导致数据分布不够优化。
3.更新聚簇索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置。 所以我们选择时一般选择基本不更新的列来做聚簇索引。
4.基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临“页分裂(page split)”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次页分裂操作。页分裂会导致表占用更多的磁盘空间。
5.聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
6.二级索引(非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点包含了引用行的主键列。这个主要是相对MyISAM来说的,因为MyISAM中二级索引存的是行号,而InnoDB的二级索引存放的是主键列,如果这个主键列很大的话,那么这个二级索引就会比MyISAM大。
二级索引
InnoDB二级索引的叶子节点中存储的不是“行指针”,而是主键值,并以此作为指向行的“指针”。这样的策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。使用主键值当作指针会让二级索引占用更多的空间,换来的好处是,InnoDB在移动行时无须更新二级索引中的这个“指针”。
总结
今天我们讲解了MySQL中的聚簇索引,明天我们还将继续介绍其他建立高性能索引的方法,敬请期待,下篇再见!