Oracle DML对于索引维护的影响

DML对于索引维护的影响

在OLTP高并发 INSERT环境中,递增列(时间,使用序列的主键列) 的索引很容易引起索引热点块争用。
递增列的索引会一直不断的往索引“最右边”的叶子块插入最新数据(因为索引默认升序排序),在高并发INSERT的时候,一次只能由一个SESSION进行INSERT,其余SESSION会处于等待状态,这样就引起了索引热点块争用。
对于递增的主键列索引,可以对这个索引进行反转(reverse),这样在高并发INSERT的时候,就不会同时插入索引“最右边”的叶子块,而是会均衡的插入到各个不同的索引叶子块中,这样就解决了主键列索引的热点块问题。
将索引进行反转之后,索引的集群因子会变得很大(基本上接近于表的总行数),此时索引范围扫描 回表会有严重的性能问题,但是一般情况下,主键列都是等值访问,索引走的是 INDEX UNIQUE SCAN,索引唯一扫描 不受集群因子的影响,所以对主键列索引进行反转没有任何问题

对于递增的时间列索引,不能对这个索引进行反转,因为时间字段会经常进行范围查找,对时间字段的索引反转之后,索引的集群因子会变得很大,会严重影响回表性能,遇到这种情况,应该考虑对表根据时间进行范围分区,利用分区裁剪来提升查询性能而不是在时间字段建立索引来提升性能。

在OLTP高并发INSERT环境中,非递增列索引(比如电话号码)一般不会引起索引热点块争用。非递增列的数据都是随机的(电话号码),在高并发INSERT的时候,数据会随机的插入到索引的各个叶子块中,因此非递增列索引不会引起索引热点块问题,但是如果索引太多会严重影响高并发INSERT的性能。

当只有1个会话进行INSERT,这时表中有1个块会发生变化,有N个索引,就有N个索引叶子块会发生变化(不考虑索引分裂的情况),假设有10个索引,那么就有10个索引叶子块发生变化。
如果有10个会话同时进行 INSERT,这时表中最多有10个块会发生变化,索引中最多有100个块会发生变化(10个SESSION*10个索引)。在高并发的INSERT环境中,表中的索引越多,INSERT速度越慢。
对于高并发INSERT,一般是采用分库分表,读写分离,和消息队列等技术来解决。

在OLAP环境中,没有高并发INSERT的情况,一般是单进程做批量INSERT。单进程做批量INSERT,可以在递增列上建立索引,因为是单进程,没有并发,不会有索引热点块争用,数据也是一直插入的索引中“最右边”的叶子块,因此递增列索引对批量INSERT影响不会太大。单进程做批量INSERT,不能在非递增列建立索引,因为批量INSERT几乎会更新索引中所有的叶子块,因此非递增列索引对批量INSERT影响很大。
在OLAP环境中,事实(FACT)表没有主键,时间列一般也是分区字段,所以递增列上面一般是没有索引的,而电话号码等非递增列往往又需要索引,为了提高批量INSERT的效率,可以在INSERT之前先禁止索引,等INSERT完成之后再重建索引。

猜你喜欢

转载自blog.csdn.net/keaihuilang/article/details/80901514