重建索引有两种方法:一种是最简单的,删除原索引,然后重建;第二种是使用ALTER INDEX … REBUILD
命令对索引进行重建。第二种方式是从oracle 7.3.3版本开始引入的,从而使得用户在重建索引时不必删除原索引再重新CREATE INDEX了。ALTER INDEX … REBUILD相对CREATE INDEX有以下好处:
它使用原索引的叶子节点作为新索引的数据来源。我们知道,原索引的叶子节点的数据块通常都要比表里的数据块要少很多,因此进行的I/O就会减少;同时,由于原索引的叶子节点里的索引条目已经排序了,因此在重建索引的过程中,所做的排序工作也要少的多。
自从oracle 8.1.6以来,ALTER INDEX … REBUILD命令可以添加ONLINE短语。这使得在重建索引的过程中,用户可以继续对原来的索引进行修改,也就是说可以继续对表进行DML操作。
而同时,ALTER INDEX … REBUILD与CREATE INDEX也有很多相同之处:
它们都可以通过添加PARALLEL提示进行并行处理。
它们都可以通过添加NOLOGGING短语,使得重建索引的过程中产生最少的重做条目(redo entry)。
自从oracle 8.1.5以来,它们都可以田间COMPUTE STATISTICS短语,从而在重建索引的过程中,就生成CBO所需要的统计信息,这样就避免了索引创建完毕以后再次运行analyze或dbms_stats来收集统计信息。
当我们重建索引以后,在物理上所能获得的好处就是能够减少索引所占的空间大小(特别是能够减少叶子
节点的数量)。而索引大小减小以后,又能带来以下若干好处:
CBO对于索引的使用可能会产生一个较小的成本值,从而在执行计划中选择使用索引。
使用索引扫描的查询扫描的物理索引块会减少,从而提高效率。
由于需要缓存的索引块减少了,从而让出了内存以供其他组件使用。
尽管重建索引具有一定的好处,但是盲目的认为重建索引能够解决很多问题也是不正确的。比如我见过一
个生产系统,每隔一个月就要重建所有的索引(而且我相信,很多生产系统可能都会这么做),其中包括一些100GB的大表。为了完成重建所有的索引,往往需要把这些工作分散到多个晚上进行。事实上,这是一个7×24的系统,仅重建索引一项任务就消耗了非常多的系统资源。但是每隔一段时间就重建索引有意义吗?这里就有一些关于重建索引的很流行的说法,主要包括:
如果索引的层级超过X(X通常是3)级以后需要通过重建索引来降低其级别。
如果经常删除索引键值,则需要定时重建索引来收回这些被删除的空间。
如果索引的clustering_factor很高,则需要重建索引来降低该值。
定期重建索引能够提高性能。
对于第一点来说,我们在前面已经知道,B树索引是一棵在高度上平衡的树,所以重建索引基本不可能降
低其级别,除非是极特殊的情况导致该索引有非常大量的碎片,导致B树索引“虚高”,那么这实际又来到第二点上(因为碎片通常都是由于删除引起的)。实际上,对于第一和第二点,我们应该通过运行ALTER INDEX … REBUILD命令以后检查indest_stats.pct_used字段来判断是否有必要重建索引。