15.6.2.3-有序索引构建

在创建或重建索引时,InnoDB使用批量加载而不是逐条插入的方式。这种创建索引的方法也叫做有序索引构建。有序索引构建不适用于空间索引。

一个索引构建过程可以分为三个阶段。在第一个阶段,扫描聚簇索引,生成索引条目并加载到sort buffer中。当sort buffer满后,索引条目被排序,并写入一个临时文件。这个过程也被称为"执行"。在第二个阶段,执行 已经向临时表写入了数据,将对文件中的记录进行归并排序。在第三个阶段,将排序后的条目写入到B-tree索引中。

在介绍索引排序构建之前,使用insert api向B-tree中添加索引记录时,都是一条一条插入的。这种方式涉及打开B-tree游标,找到插入位置,然后向一个B-tree页面中插入条目,这种插入时乐观插入。如果因为页面满了导致插入失败,就会执行悲观插入,这时会打开B-tree游标,分裂或者合并页面来为条目找到空间(如果需要的话)。这种自上而下的方法的缺点,在于搜索插入位置的成文,以及页分裂和页合并的成本。

有序索引构建使用“自底向上”的方式来构建索引。在这种方式中,在B-tree的每一层中,都保留对最右边的叶子页面的引用。对应深度的最右节点被定位到后,相关记录条目按照顺序插入。如果一个叶子页面满了,就会在父页面添加一个节点指针,并在本层添加一个页面为新的插入桌准备。直到所有条目都被插入,这个过程会持续,可能会涉及到顶层节点的插入。

在分配一个兄弟页面后,对前一个页面的引用会被释放,新的页面就会变成最右页面,称为默认插入位置。

为未来索引数据增长保留B-tree页面空间 #

要为未来的索引增长保留空间,你可以使用innodb_fill_factor变量,来保留一定比例的B-tree页面空间。例如,将innodb_fill_factor设置为80,就会保留20%的空间。这个设置对B-tree的叶子节点和非叶子节点同样适用。对TEXT和BLOB的溢出页不适用。保留的空间带下可能和设置的不同,因为innodb_fill_factor更像是一个提示而非硬性限制。

有序索引构建和全文索引支持 #

有序索引构建支持全文索引。之前,使用SQL将条目插入的全文索引中。

有序索引构建和压缩表 #

对于压缩表来说,之前的索引创建方法会向压缩页面和非压缩页面添加条目。当修改日志(代表着压缩页面中的空闲空间)变满后,压缩页面就会被重新叶索。如果因为压缩失败导致压缩失败,页面就会被分裂。在有序索引构建中,条目只会被住家在非压缩页面中。当非压缩页面变满时,它就会被压缩。为了保证大多数情况下都能成功压缩,会添加自使用填充。但是如果真的压缩失败了,页面会进行分裂,然后再次压缩,直到压缩成功。想了解更多关于B-Tree页面压缩的信息,请查阅章节15.9.1.5 ,“How Compression Works for InnoDB Tables”。

有序索引构建和Redo Logging #

在有序索引构建时,Redo Logging会被禁用。作为替代,会使用一个检查点来确保索引构建可以经得起意外退出或失败。在checkpoint会强制刷脏页到磁盘。在一个有序索引构建过程中,会定期通知页面清理线程刷脏页,以确保checkpost操作可以快速处理。通常,当干净页面的数量低于一个阈值时,页面清理线程会主动刷脏。对于排序索引构建来说,主动刷脏是为了减少checkpoint时的压力,并行化I/O和cpu活动。

有序索引构建和优化器统计 #

有序索引构建产生的优化器统计信息可能和之前的索引创建方法不同。不同的原因是为了不影响工作负载性能而采取的不同算法。