暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

INDEX 肥胖化

IT界数据库架构师的漂泊人生 2020-12-14
374


索引会逐步地膨胀下去,会发肥 肥到超过表大小还不停歇下来的.

索引变肥了 有如下后果

1 占用大量的磁盘空间

2 如果该索引被使用,就要占用大量的BUFFER内存空间

3 对索引范围扫描和快速全索引扫描不利


所以要定期重建索引.

当要怎么样才知道,哪些索引要重建呢?


我有个对比表 比如单列索引的字段大小,和表的平均行大小的比值.

然后索引大小跟表大小的比值. 再拿两个比值对比,看差异是否逐渐扩大.

表:TRADERECORD              

索引: IX_TR_DATETIME                         

索引列大小:11        

表平均行大小: 686           

列行比率 1.6035 %

索引大小 403 MB

表大小   3932   MB

索引表比率:10.2492 %

表率与字段率 比值  6.391797倍


那么我们该重建此索引. 我们有3个办法来评估新索引的大小.

1 新建一样的表,然后把表的数据插入该新表,在新表上建一样的索引

 

create table test1 as select * from  trade_record;

select * from dba_segments s where s.segment_name='IX_TR_DATETIME';

select * from dba_segments s where  s.segment_name='IX_TR_DATETIME2';


旧索引的段信息

SEGMENT_NAME IX_TR_DATETIME

BYTES                  212860928

BLOCKS                  25984


新索引的段信息

SEGMENT_NAME IX_TR_DATETIME2

BYTES                 117440512

BLOCKS                 14336


旧的索引大小203MB, 新索引大小112MB


2 使用DBMS_SPACE 包来评估

set serveroutput on;

SQL>

declare

 l_index_ddl       varchar2(1000);

 l_used_bytes      number;

 l_allocated_bytes number;

 begin

 dbms_space.create_index_cost

(ddl         => 'create index IX_TR_DATETIME3 on ossc.ccps_traderecord(TR_DATETIME) ',

used_bytes  => l_used_bytes,

alloc_bytes => l_allocated_bytes);

dbms_output.put_line('used= ' || l_used_bytes ||  ' bytes' ||

  '     allocated= ' || l_allocated_bytes || ' bytes');

 end;

 /

used= 45615955 bytes     allocated= 100663296 bytes

PL/SQL procedure successfully completed

  allocated= 100663296 bytes =>96MB


3 执行计划

explain plan for create index IX_TR_DATETIME3 on trade_record(TR_DATETIME) ;

SQL> set linesize 200 pagesize 1400;

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 1698331371

--------------------------------------------------------------------------------

| Id  | Operation              | Name            | Rows  | Bytes | Cost (%CPU)|

--------------------------------------------------------------------------------

|   0 | CREATE INDEX STATEMENT |                 |  4146K|    43M|  9022   (1)|

|   1 |  INDEX BUILD NON UNIQUE| IX_TR_DATETIME3 |       |       |            |

|   2 |   SORT CREATE INDEX    |                 |  4146K|    43M|            |

|   3 |    INDEX FAST FULL SCAN| IX_TR_DATETIME  |  4146K|    43M|  6924   (1)|

--------------------------------------------------------------------------------

Note

-----

   - estimated index size: 100M bytes

14 rows selected


这里看到评估索引大小为100MB, 使用43MB


索引为什么发福呢?

1 索引分裂

索引是个有序的平衡树,当新来的数据需要插入有序的队伍中

2 索引删除

当更新数据字段的时候,索引先把旧的给打上删除标记,然后在新的地方存新数据

3 并发插入

并发插入的时候 在一定时间内的插入数据 会合并在一定的块里面,然后连接到索引的树上. 而这个块除了PCTFREE规定的空闲空间外,它不会插满的.还有空闲的空间. 这样下去造成大量的索引块都未满.


这就是我这个索引列 是交易时间,少于更新,少于删除,少于分裂,当并发插入还是蛮高的.


那我们看下新旧索引的结构

analyze index IX_TR_DATETIME2 validate structure;

analyze index IX_TR_DATETIME  validate structure; 


新旧索引差异列

                                           旧             新

LF_BLKS                        25039         13315

LF_ROWS_LEN      9554,4075       9,5537,635

LF_BLK_LEN                  3988            7966

BR_ROWS                    25038          13314

BR_BLKS                            59               28

BR_ROWS_LEN         40,4563      21,5709

DEL_LE_ROWS                280                 0

DEL_LF_ROWS_LEN     6440                 0

BTREE_SPACE   1,0032,9184  1,0669,1524

USED_SPACE       95948638    95753344

PCT_USED                      96                 90


从对比效果来看得出来,旧的叶块的行长度比新的短很多,那么同样的数据就需要更多的叶块来存,更多的叶块就要更多的分支块


如果本号文对你有意义可以下我打赏,金额多少无所谓!



文章转载自IT界数据库架构师的漂泊人生,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论