今天早上骑电屏车上班时突然想到了一个问题,昨天看了些PG的有关MVCC的资料,PG在处理 UPDATE,DELETE 语句时,不会立即删除掉旧的记录,而是将旧的记录保存一段时间,直到VACCUM之后才会真正删除旧的记录,我在想,当DELETE语句时PG保留原有的记录这很好理解,但是当UPDATE时,PG是保留UPDATE的整行记录,还是仅保留那条记录被UPDATE的字段,带着这个疑问,做了以下测试。
创建测试表
创建测试表并插入100万数据
1 2 3 4
|
mydb=> create table test_7 (id integer, remark varchar(32)) CREATE TABLE mydb=> insert into test_7 select generate_series(1,1000000),'aaaaaa' INSERT 0 1000000
|
查看表大小和占用PAGE
查看表大小
1 2 3 4 5
|
mydb=> select pg_size_pretty(pg_relation_size('test_7')) pg_size_pretty ---------------- 38 MB (1 row)
|
这里看出表 test_7 为 38 M。
查看表的page数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
mydb=> /d pg_class Table "pg_catalog.pg_class" Column | Type | Modifiers -----------------+-----------+----------- relname | name | not null relnamespace | oid | not null reltype | oid | not null reloftype | oid | not null relowner | oid | not null relam | oid | not null relfilenode | oid | not null reltablespace | oid | not null relpages | integer | not null reltuples | real | not null reltoastrelid | oid | not null reltoastidxid | oid | not null relhasindex | boolean | not null relisshared | boolean | not null relistemp | boolean | not null relkind | "char" | not null relnatts | smallint | not null relchecks | smallint | not null relhasoids | boolean | not null relhaspkey | boolean | not null relhasexclusion | boolean | not null relhasrules | boolean | not null relhastriggers | boolean | not null relhassubclass | boolean | not null relfrozenxid | xid | not null relacl | aclitem[] | reloptions | text[] | Indexes: "pg_class_oid_index" UNIQUE, btree (oid) "pg_class_relname_nsp_index" UNIQUE, btree (relname, relnamespace)
mydb=> analyze test_7; ANALYZE
mydb=> select relname,relpages,reltuples from pg_class where relname='test_7'; relname | relpages | reltuples ---------+----------+----------- test_7 |4902 | 1e+06 (1 row)
|
这里可以看出表 test_7 有4902 page。测试UPDATE, 并再次查看表大小和占用 page数
UPDATE表
1 2 3 4 5 6 7 8 9 10 11
|
mydb=> update test_7 set remark='bbbbbb'; UPDATE 1000000
mydb=> select relname,relpages,reltuples from pg_class where relname='test_7'; relname | relpages | reltuples ---------+----------+----------- test_7 | 4902 | 1e+06 (1 row)
mydb=> analyze test_7; ANALYZE
|
再次查看表大小和占用PAGE
1 2 3 4 5 6 7 8 9 10 11
|
mydb=> select relname,relpages,reltuples from pg_class where relname='test_7' relname | relpages | reltuples ---------+----------+----------- test_7 | 9804 | 1e+06 (1 row)
mydb=> select pg_size_pretty(pg_relation_size('test_7')) pg_size_pretty ---------------- 77 MB (1 row)
|
从上面看出,表的PAGE数为9804,刚好增加了一倍,这也说明,PG处理UPDATE语句时,也是保留了原有记录的一份,只是在存储上标记为不可读而已,同时也说明,保留的是原有的记录整行,而不只是更新的字段值。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/236343.html