iT邦幫忙

1

以Postgresql為主,再聊聊資料庫 五探Postgresql Catalog

之前寫的  以Postgresql為主,聊聊資料庫
有一篇 四探 Postgresql Catalog 

https://ithelp.ithome.com.tw/articles/10218574

是關於建立 table 時,pg_catalog 會發生什麼變化.

今天來跟大家聊聊刪除欄位時,pg_catalog 裡關於欄位屬性的
pg_attribute, 以及 disk space.

create table foo200210 (
  n int not null
);

-- insert 一千萬筆
insert into foo200210 
select generate_series(1, 10000000);

INSERT 0 10000000
Time: 15468.770 ms (00:15.469)

commit;

-- query table size
select pg_size_pretty(pg_relation_size('foo200210'));

+----------------+
| pg_size_pretty |
+----------------+
| 346 MB         |
+----------------+

-- 接著增加一個 text 欄位,存放隨機資料.
alter table foo200210
  add column t text default md5(random()::text);

ALTER TABLE
Time: 32292.338 ms (00:32.292)

新增一千萬筆隨機文字資料,花費約32秒.

commit;

-- query table size
select pg_size_pretty(pg_relation_size('foo200210'));

+----------------+
| pg_size_pretty |
+----------------+
| 651 MB         |
+----------------+

可以觀察到 table size 幾乎倍增.
接著來看看 pg_catalog 裡面關於欄位的一些屬性

select attnum
     , attname
     , attisdropped
  from pg_attribute a
  join pg_class c
    on c.oid = a.attrelid
   and c.relname = 'foo200210'
   and c.relkind = 'r'
   and a.attnum > 0;

+--------+---------+--------------+
| attnum | attname | attisdropped |
+--------+---------+--------------+
|      1 | n       | f            |
|      2 | t       | f            |
+--------+---------+--------------+
(2 rows)

可以觀察到兩個欄位的屬性中有 "是否已經刪除" (attisdropped), 目前都是 false

接著我們來把 text 型態的欄位刪除.

alter table foo200210
 drop column t;

ALTER TABLE
Time: 15.217 ms

觀察到只用了 15.217 ms. 

commit;

接著來看欄位情況以及size

select attnum
     , attname
     , attisdropped
  from pg_attribute a
  join pg_class c
    on c.oid = a.attrelid
   and c.relname = 'foo200210'
   and c.relkind = 'r'
   and a.attnum > 0;

+--------+------------------------------+--------------+
| attnum |           attname            | attisdropped |
+--------+------------------------------+--------------+
|      1 | n                            | f            |
|      2 | ........pg.dropped.2........ | t            |
+--------+------------------------------+--------------+

select pg_size_pretty(pg_relation_size('foo200210'));

+----------------+
| pg_size_pretty |
+----------------+
| 651 MB         |
+----------------+

可以看到 size 不變,欄位屬性被標示為已刪除(true).欄位名稱改了.
試試看能不能查詢?

select n
     , "........pg.dropped.2........"
  from foo200210
 limit 1;
ERROR:  42703: column "........pg.dropped.2........" does not exist

看到size 不變,相信對 Postgresql 比較熟悉的讀者,應該會想到 vacuum.

我們先來增加另一個欄位,再觀察size與欄位屬性.

alter table foo200210
  add column t2 text default md5(random()::text);

ALTER TABLE
Time: 34409.649 ms (00:34.410)

commit;

select attnum
     , attname
     , attisdropped
  from pg_attribute a
  join pg_class c
    on c.oid = a.attrelid
   and c.relname = 'foo200210'
   and c.relkind = 'r'
   and a.attnum > 0;

+--------+------------------------------+--------------+
| attnum |           attname            | attisdropped |
+--------+------------------------------+--------------+
|      1 | n                            | f            |
|      2 | ........pg.dropped.2........ | t            |
|      3 | t2                           | f            |
+--------+------------------------------+--------------+
(3 rows)

select pg_size_pretty(pg_relation_size('foo200210'));
+----------------+
| pg_size_pretty |
+----------------+
| 651 MB         |
+----------------+

可以觀察到 size 相同(只是size值相同),
新增了欄位 t2.
接著做 vacuum .

commit;
vacuum full foo200210;

VACUUM
Time: 17088.505 ms (00:17.089)

真的清理了.花了約17秒.

size 還是相同.

select pg_size_pretty(pg_relation_size('foo200210'));
+----------------+
| pg_size_pretty |
+----------------+
| 651 MB         |
+----------------+

select attnum
     , attname
     , attisdropped
  from pg_attribute a
  join pg_class c
    on c.oid = a.attrelid
   and c.relname = 'foo200210'
   and c.relkind = 'r'
   and a.attnum > 0;
   
+--------+------------------------------+--------------+
| attnum |           attname            | attisdropped |
+--------+------------------------------+--------------+
|      1 | n                            | f            |
|      2 | ........pg.dropped.2........ | t            |
|      3 | t2                           | f            |
+--------+------------------------------+--------------+
(3 rows)

佔的位置還是在 pg_attribute 裡面.後續新增欄位,就是遞增,不往上遞補位置.

相信透過上面操作及觀察,對 Postgresql 的 Table 空間,欄位屬性以及 vacuum 機制,
會有更清楚的理解.


尚未有邦友留言

立即登入留言