索引膨胀:乱序插入的副作用

发表时间: 2021-08-03 16:07


作者:阎书利


在对索引进行重建的时候,发现索引比原来更小。


针对这个现象,进行了如下测试:


1.数据库版本为PostgreSQL12.1


[postgres@ysla ~]$ postgres --versionpostgres (PostgreSQL) 12.1


2.先建表t1_ysl和索引ind_l,之后按乱序插入数值


postgres=# create table t1_ysl(id int);CREATE TABLEpostgres=# create index ind_l on t1_ysl(id);CREATE INDEXpostgres=# insert into t1_ysl select random()*10000000 from generate_series(1,10000000);INSERT 0 10000000


//插入10000000个1-10000000之间的随机整数


postgres=# \di+                         List of relationsSchema | Name  | Type  |  Owner   | Table  |  Size  | Description--------+-------+-------+----------+--------+--------+-------------public | ind_l | index | postgres | t1_ysl | 284 MB |(1 row)


重建索引后,查看索引大小,索引占用明显下降


postgres=# reindex index ind_l ;REINDEXpostgres=# \di+                         List of relationsSchema | Name  | Type  |  Owner   | Table  |  Size  | Description--------+-------+-------+----------+--------+--------+-------------public | ind_l | index | postgres | t1_ysl | 214 MB |(1 row)


3.清除数据,先建立索引,并顺序写入数据


postgres=# truncate t1_ysl ;TRUNCATE TABLEpostgres=# \di+                           List of relationsSchema | Name  | Type  |  Owner   | Table  |    Size    | Description--------+-------+-------+----------+--------+------------+-------------public | ind_l | index | postgres | t1_ysl | 8192 bytes |(1 row)postgres=# insert into t1_ysl select generate_series(1,10000000);  INSERT 0 10000000


//顺序插入1-10000000的数值


postgres=# \di+                         List of relationsSchema | Name  | Type  |  Owner   | Table  |  Size  | Description--------+-------+-------+----------+--------+--------+-------------public | ind_l | index | postgres | t1_ysl | 214 MB |(1 row)


4.先顺序写入数据,后建立索引


postgres=# create index ind_l on t1_ysl(id);CREATE INDEXpostgres=# \di+                         List of relationsSchema | Name  | Type  |  Owner   | Table  |  Size  | Description--------+-------+-------+----------+--------+--------+-------------public | ind_l | index | postgres | t1_ysl | 214 MB |(1 row)


现象:顺序写入时,索引大小和后建索引大小一致,没有出现膨胀。数据乱序写入时,索引明显占用更大的空间。


结论:索引页里的数据是有序的,索引字段乱序写入,导致索引频繁分裂,使得索引页没有被完全被占用。最终导致索引膨胀。


处理方法:重建索引。