Oracle的索引分裂和索引维护(精)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bless2015/article/details/84072703

索引不是建好了就行了?难道还需要维护?带着这个问题,开启本篇博客。
我们知道索引的数据结构是B树,每次更新数据都会对索引进行更新,所以如果是一张订单表,看起来这张表会一直在增长,并且订单表会经受一定的高并发考验(比如各种大促活动,秒杀活动)。对于开发人员来说,好像只对表操作就可以了,不用管oracle是如何做的,但实际上,若想清清楚楚、明明白白了解你写的接口,只有业务逻辑可不行,必须深入去知道索引是如何更新、生产、分裂的,然后才能根据具体的业务,来维护合适的索引。你的程序慢,可能是因为这个问题。

索引分裂

根据B树的理论,插入数据会使树的结构经过旋转已达到平衡,树的平衡对于树的查询效率来说至关重要。好在数据结构的知识以及解决了这个问题。oracle的索引也一样,当我们创建一个索引,并插入了100000行数据,这个插入的过程,oracle的索引是在随时发生变化的。每个枝、叶所存储的块大小、数量也是可配置的。那么索引是如何分裂的?
索引分裂有两种形式:9-1分裂,5-5分裂。场景不同时,发生不一样的分裂方式。

9-1分裂:绝大部分数据保留在旧节点上海,仅有非常小的一部分数据迁移到新节点。
5-5分裂:旧节点和新节点上的数据比例几乎是持平的。

5-5分裂的触发条件:

  1. 当树的左侧发生新值插入时(新值小于索引中的最大值)
  2. 发生DML操作,索引块上没有足够空间分类新的ITL槽
  3. 新值所插入的索引块上存在其他未提交的事务

5-5分裂看起来会让索引变得虚胖。
2和3的发生概率和影响程度都很高,尤其当高并发事件时。

高并发

高并发时,插入操作过于集中在右侧的索引块上。对索引进行高并发优化的一个操作是创建反键索引,比如我们要存储数据“10001”,“10002”,“10003”。这三个数很大几率会存在一个索引块上,如果创建反键索引,以上数据就会变成“10001”,“20001”,“30001”,相当于把数据打散了。
细心的人会问,数据打散了,那本来我做范围查询就可以走INDEX RANGE SCAN就可以的,这样一来岂不是要走INDEX FULL SCAN,降低查询效率?没错。凡事有利有弊,索引应用反键索引最好做等值查询,否则会增加I/O开销。经过数据统计,反键索引有数倍于普通索引的性能提升(TPS),所以还是很值得考虑的。

索引维护

设计的再好的索引,经过考验,特别是高并发的考验后,也会变得效率低下。所以索引需要进行后期的优化。我们先来看为什么会索引会变的效率低下。
索引的更新有三种操作:INSERT,UPDATE,DELETE。而索引的DELETE并不是实际删除,执行DELETE后,知识将其内容清空,但节点还在(因为物理删除一个树的节点是很消耗资源的),当碎片多了以后,索引变得非常松散,会影响到索引的性能。

索引重建

条件:

  1. 索引树高度过高,比如>=4
  2. 叶节点碎片过多,比如DEL_LF_ROWS/LF_ROWS>20%
  3. 叶节点使用率低下,比如PCT_USAGE<20%

笨方法:

  1. 分析索引结构
analyze index idx_test_id validate structure;
  1. 从index_stata中获取我们要的信息
select height,round((del_lf_rows_len/lf_rows_len)*100,2||'%' ratio,pct_used from index_stats where name='idx_test_id';

本方法之所以笨,因为第一步分析过程时间长,在分析的过程中会锁表,线上系统几乎不能忍受。
好方法:

通过估算

  • 估算出单个索引空间的存储大小 INDEX_ROW_LEN = 10+COL_LEN
  • 索引块可以存储的索引数量(BLOCK_SIZE-192),192是数据库保留部分。考虑预留比例,就是当索引数量超过索引块一定大小时就会进行分裂,这个比例是PCTFREE存储的。所以单个索引块存储索引的条目为(BLOCK_SIZE-192)*(1-PCTFREE)/INDEX_ROW_LEN
  • 计算索引的条目数,差不多等于行记录数,但不一定。记为:NUM_INDEX_ROWS
  • 计算存储这些数据需要多少个索引块 NUM_INDEX_ROWS/((BLOCK_SIZE-192)*(1-PCTFREE)/INDEX_ROW_LEN)
  • 索引块利用率为(1-上面这个大长式子)*100%

基于这个估算数可以评估索引块利用率,判断是否需要对索引进行重建。

索引重建

大致有两种方式:重组和重建。又分为:在线和离线。
离线重组

alter index idx_test_id shrink space;

在线重组

alter index idx_test_id coalesce;
--(coalesce:联合、合并)

离线重建

alter index idx_test_id rebuild;

在线重建

alter index idx_test_id rebuild online;

coalesce不会收回索引上的空闲空间,shrink space回收的也不彻底。所以比较好的折中方案是在空闲时间对索引进行在线重建,实质上是对表进行重新扫描,重新建一个新的。

猜你喜欢

转载自blog.csdn.net/bless2015/article/details/84072703