关闭

pg_attribute表容量膨胀问题分析

298人阅读 评论(0) 收藏 举报
分类:

PG数据库下表字段更新对pg_attribute表空间影响:

1)TEST数据库下已有一张class表,信息如下,包含两个字段int类型的num和varchar(20)类型的name:

    TEST=# \d class
         资料表 "public.class"
     栏位 |         型别          | 修饰词
    ------+-----------------------+--------
     num  | integer               | 非空
     name | character varying(20) |

2)查看此时存储在pg_attribute表中class表的字段信息,结果如下:

    TEST=# select attrelid,attname from pg_attribute a, pg_class b where a.attrelid=b.oid and b.relname='class';
    -[ RECORD 1 ]------
    attrelid | 35012
    attname  | cmax
    -[ RECORD 2 ]------
    attrelid | 35012
    attname  | cmin
    -[ RECORD 3 ]------
    attrelid | 35012
    attname  | ctid
    -[ RECORD 4 ]------
    attrelid | 35012
    attname  | name
    -[ RECORD 5 ]------
    attrelid | 35012
    attname  | num
    -[ RECORD 6 ]------
    attrelid | 35012
    attname  | tableoid
    -[ RECORD 7 ]------
    attrelid | 35012
    attname  | xmax
    -[ RECORD 8 ]------
    attrelid | 35012
    attname  | xmin

从结果中看到pg_attribute表中存储着class表的8个字段,除了自己定义的num和name之外,其他6个位默认隐含字段。

3)如果更新了class表的一个字段,更新后的字段信息会存储到pg_attribute表,旧的字段信息将被标记为删除状态,成为dead数据。在更新class表字段之前,先查询出当前pg_attribute表的live和dead记录,查询结果如下:

    TEST=# select relname, n_live_tup,n_dead_tup from pg_stat_sys_tables a where a.relname='pg_attribute';
    -[ RECORD 1 ]------------
    relname    | pg_attribute
    n_live_tup | 2428
    n_dead_tup | 257

可以看到,目前pg_attribute表的live记录为2428,dead记录为257;

4)现在更新class表的name字段名称,然后再次查询pg_attribute表的live记录和dead记录,结果如下:

    TEST=# alter table class rename column name to name2;
    ALTER TABLE
    TEST=# select relname, n_live_tup,n_dead_tup from pg_stat_sys_tables a where a.relname='pg_attribute';
    -[ RECORD 1 ]------------
    relname    | pg_attribute
    n_live_tup | 2428
    n_dead_tup | 258

可以看到,在把class表的name字段名称更新为name2后,pg_attribute表的live记录未变化,dead记录由257变为258,说明pg_attribute中多了一条dead记录,这条记录就是被更新的name字段。

5)现在测试创建和删除临时表对pg_attribute表的影响,先创建一个临时表:

    TEST=# create temp table tempT(
    TEST(# id int);
    CREATE TABLE
    TEST=# select relname, n_live_tup,n_dead_tup from pg_stat_sys_tables a where a.relname='pg_attribute';
    -[ RECORD 1 ]------------
    relname    | pg_attribute
    n_live_tup | 2435
    n_dead_tup | 258

创建临时表tempT,只包含一个int类型的id字段。创建后查询pg_attribute信息,可以看到live记录由2428变为了2435,增长了7,结合步骤2)中实验得出的每张表默认包含6个隐藏字段,刚好此处增长的7个字段为tempT表的字段。

6)删除临时表tempT,删除后查看pg_attribute表信息:

    TEST=# drop table tempT;
    DROP TABLE
    TEST=# select relname, n_live_tup,n_dead_tup from pg_stat_sys_tables a where a.relname='pg_attribute';
    -[ RECORD 1 ]------------
    relname    | pg_attribute
    n_live_tup | 2428
    n_dead_tup | 265

删除后,可以看到live记录重新变回了2428,而dead记录变为了265,相比258增长了7。这增长的7条dead记录即为tempT临时表中的7个字段信息。

总结

所以如果频繁的用到临时表,需要注意pg_attribute表的dead空间清理。可以使用vacuum操作或者cluster操作是否dead空间。
即vacuum full tablename。
cluster tablename using index。

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:14365次
    • 积分:318
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章分类