原作者:姜殿斌
看到一个说法: 如果数据发生大量删除后,索引页面上的索引键将被删除,导致索引页面数量的减少,造成索引膨胀。重建索引可回收浪费的空间。
我们通过下面的实验,验证这个说法是否正确。
1、实验环境
1)创建表:
[omm@node1 ~]$ gsql -r`
`gsql ((MogDB 5.0.3 build 86d963ad) compiled at 2023-10-13 09:17:48 commit 0 last mr 1804 )`
`Non-SSL connection (SSL connection is recommended when requiring high-security)`
`Type "help" for help.
MogDB=#
drop table if exists test1;
create table test1(
id int primary key,
number1 int,
number2 int);
2)插入数据、创建索引:
insert into test1 select i,i,0 from generate_series(1,1000000) as i;
create index test1_number1_idx on test1(number1);
2、实验过程
1)查看表和索引所占的块数
MogDB=# \x`
`Expanded display is on.
MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1';`
`-[ RECORD 1 ]------`
`relname | test1`
`reltype | 17123`
`relpages | 5406`
`reltuples | 1000000
MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1_number1_idx';`
`-[ RECORD 1 ]--------------------`
`relname | test1_number1_idx`
`reltype | 0`
`relpages | 2752`
`reltuples | 1000000
2)删除表数据后,再次查看表和索引锁占的块数:
MogDB=# delete from test1 where id>100;`
`DELETE 999900`
`MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1';`
`-[ RECORD 1 ]----`
`relname | test1`
`reltype | 17081`
`relpages | 5406`
`reltuples | 100
MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1_number1_idx';
-[ RECORD 1 ]----------------`
`relname | test1_number1_idx`
`reltype | 0`
`relpages | 2752`
`reltuples | 100
说明:
删除数据后,没有新数据插入时,表、索引的占用的页面数均不变。
3)autovacuum后,查看表和索引锁占的块数:
由于默认打开了autovacuum,所以,系统会自动出发autovacuum操作,不用手动 vacuum 。
当然,也可以手动执行vacuum test1。
MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1';
-[ RECORD 1 ]----
relname | test1
reltype | 17081
relpages | 1
reltuples | 100
说明:表的使用空间从5406减少到1个page。
MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1_number1_idx';
-[ RECORD 1 ]--------------------
relname | test1_number1_idx
reltype | 0
relpages | 2752
reltuples | 100
说明:索引的使用空间则没有变化,仍是2752个pages 。
4)重建索引,解决索引膨胀。
查看索引锁占的块数:
MogDB=# reindex table test1;`
`REINDEX`
`MogDB=# select relname,reltype,relpages,reltuples from pg_class where relname='test1_number1_idx';`
`-[ RECORD 1 ]--------------------`
`relname | test1_number1_idx`
`reltype | 0`
`relpages | 2`
`reltuples | 100
说明: reindex后,索引占用的块数从2752减少到2pages。
4、结论:
删除数据后,没有新数据插入时,索引页面数不变。
**原因:**是在Astore引擎中,删除仅仅在块中做了标记,并未真正删除。
reindex重建索引后,才真正删除,占用的块数才变小,即通过重建索引,解决索引膨胀问题。
通过实验验证, 文章开头提到的说法不是十分准确。可以改为:
“如果数据发生大量删除后,索引页面上的索引键将被删除,索引数量变小,但是索引占用页面的数量未变,造成索引膨胀。重建索引可回收浪费的空间。”
5、附录:
1、pg_class说明:
参考:https://docs.mogdb.io/zh/mogdb/v5.0/PG_CLASS
说明:relpages,以页(大小为BLCKSZ)为单位的此表在磁盘上的大小,它只是优化器用的一个近似值。但是不影响观测存储空间的变化。
2、实验中涉及的autovacuum的参数:
MogDB=# show track_counts;`
`-[ RECORD 1 ]+---`
`track_counts | on
MogDB=# show autovacuum_max_workers;`
`-[ RECORD 1 ]----------+---`
`autovacuum_max_workers | 10
MogDB=# show autovacuum_mode;`
`-[ RECORD 1 ]---+----`
`autovacuum_mode | mix
MogDB=# show autovacuum;`
`-[ RECORD 1 ]--`
`autovacuum | on




