PostgreSQL索引膨胀

我们在使用数据库的时候经常会遇到索引膨胀的情况,一般我们都会选择去重建索引,这种情况在oracle、mysql等数据库中都经常发生,而在pg中也会有同样的问题,是什么原因导致索引膨胀呢?

一般来说,通常是因为数据乱序写入导致的,我们都知道索引页中的数据是有序的,而索引字段乱序写入,会导致索引频繁分裂,使得索引页并不是百分百填满,自然出现索引膨胀的情况。

在pg中的btree、gin、gist索引等都会有这样的问题。

b-tree索引:
1、先创建索引,再乱序写入数据
索引大小为284MB

bill=# create table t_idx(id int);
CREATE TABLE
bill=# create index idx_t_idx on t_idx using btree(id);
CREATE INDEX
bill=# insert into t_idx select random()*10000000 from generate_series(1,10000000);  
INSERT 0 10000000
bill=# \di+ idx_t_idx 
                         List of relations
 Schema |   Name    | Type  | Owner | Table |  Size  | Description 
--------+-----------+-------+-------+-------+--------+-------------
 bill   | idx_t_idx | index | bill  | t_idx | 284 MB | 
(1 row)

2、先创建索引,再顺序写入数据
索引大小214MB

bill=# truncate t_idx ;
TRUNCATE TABLE
bill=# insert into t_idx select generate_series(1,10000000);
INSERT 0 10000000
bill=#  \di+ idx_t_idx
                         List of relations
 Schema |   Name    | Type  | Owner | Table |  Size  | Description 
--------+-----------+-------+-------+-------+--------+-------------
 bill   | idx_t_idx | index | bill  | t_idx | 214 MB | 
(1 row)

3、先插入数据再创建索引

bill=# drop index idx_t_idx ;
DROP INDEX
bill=# create index idx_t_idx on t_idx using btree(id);
CREATE INDEX
bill=#  \di+ idx_t_idx
                         List of relations
 Schema |   Name    | Type  | Owner | Table |  Size  | Description 
--------+-----------+-------+-------+-------+--------+-------------
 bill   | idx_t_idx | index | bill  | t_idx | 214 MB | 
(1 row)

可以发现,顺序写入数据的索引大小和重建索引后的索引大小一样,说明:顺序写入并不会导致索引膨胀。

同样,gin,gist索引也都是树形结构,也会有同样的膨胀的问题,所以我们都需要对出现膨胀的索引进行重建以解决该问题。
pg中重建索引支持:在同一列再创建一个新的索引,然后旧的膨胀的索引。或者使用concurrently参数来并行重建索引,也可以避免dml堵塞,语法为:

CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
    ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
    [ INCLUDE ( column_name [, ...] ) ]
    [ WITH ( storage_parameter = value [, ... ] ) ]
    [ TABLESPACE tablespace_name ]
    [ WHERE predicate ]
发布了70 篇原创文章 · 获赞 5 · 访问量 3110

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/103962197