索引的第二项成本是,只要对表进行修改就会花费的时间。
以下描述假设,定位某个索引条目时大约需要读取两页。 如果索引包含一个根页、一层枝页和一组叶子页,就属于这种情况。 假设根页已经在缓冲区中。 对于很大的表,其索引至少有两层中间层,因此数据库服务器引用这样一个索引时,大约会读取三页。
大概而言,定位一个正在改变的行,需要使用一个索引。 用于该索引的页可能会在数据库服务器的共享内存中的页缓冲区中找到。 然而,用于其他任何需要改变的索引的页都必须从磁盘中读取。
数据库服务器必须查找已删除行(两页或三页读入)的条目,并重写叶子页。 更新该索引的写操作在内存中执行,并且在清除包含修改过的页的最近最少使用的 (LRU) 缓冲区清除后就会刷新叶子页。此操作必须 访问两或三页以对索引页进行读取操作(如果需要),还必须访问一个延迟页以对修改页进行写操作。
数据库服务器必须找到一个地方,用于输入每个索引中(两或三页读入)插入的行并重写(一个延迟的页输出),因此每个索引需要访问三个或者四个中间页。
数据库服务器必须重写叶子页,从而消除旧的条目(一个延迟页输出),然后在同一个索引中定位新的列值(再读入两页或三页)和输入的行(再导出另一个延迟页)。
插入和删除会更改叶子页中的索引数。 尽管实际上每个 pagents 操作 均要求一些附加工作,以处理填充或清空的叶子页,但 如果 pagents 大于 100,这些 附加工作所花费的时间不会超过总时间的 1%。 估计 I/O 影响时,常常将其忽略。
简而言之,如果随机插入或删除一行,大约每个索引要增加三到四页的 I/O 操作。更新某行时,对于应用于变更列的每个索引,大约要增加六到八页的 I/O 操作。如果事务回滚,那么所有此类工作必须撤销。出于这种原因,回滚事务会花费很长的时间。
由于行本身的变更只需要两页的 I/O 操作,所以索引维护显然是数据修改中最耗时的部分。有关减少此成本的一种方法的信息,请参阅集群。