Postgresql

postgres 是否有效地重用已刪除行中的空間?

  • May 29, 2014

文件

在 PostgreSQL 中,行的 UPDATE 或 DELETE不會立即刪除該行的舊版本

$$ … $$但最終,任何事務都不再對過時或刪除的行版本感興趣。然後必須回收它佔用的空間以供新行重用,以避免磁碟空間需求的無限增長。這是通過執行 VACUUM來完成的。

當真空執行時,它是否通過重寫整個塊來有效地釋放被刪除行佔用的空間,或者只有當新行小於為它們讓路的已刪除行時才會出現塊碎片,新行適合可用的“洞” ?

VACUUM 重寫整個塊,有效地打包剩餘的行並留下一個連續的空閒空間塊(儘管這個空間沒有歸零,並且物理磁碟文件可能包含已刪除行的剩餘部分,當然這些剩餘部分對數據庫使用者)。

測試時間表:

--#psql postgres postgres
select oid from pg_database where datname='postgres';
/*
 oid
-------
12035
*/
create schema stack;
set search_path=stack;
create table foo(bar text);
insert into stack.foo(bar) values('row 1');
insert into stack.foo(bar) values('row 2');
checkpoint;
select * from foo;
/*
 bar
-------
row 1
row 2
*/
select relfilenode
from pg_class c join pg_namespace n on n.oid=c.relnamespace
where nspname='stack' and relname='foo';
/*
relfilenode
-------------
     446488
*/

表支持文件的物理內容:

xxd -a /var/lib/postgresql/9.3/main/base/12035/446488

0000000: 3800 0000 f093 9d83 0000 0000 2000 c01f  8........... ...
0000010: 0020 0420 0000 0000 e09f 3c00 c09f 3c00  . . ......<...<.
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
0001fc0: 2176 4c14 0000 0000 0000 0000 0000 0000  !vL.............
0001fd0: 0200 0100 0208 1800 0d72 6f77 2032 0000  .........row 2.. <---- this is row 2
0001fe0: 2176 4c14 0000 0000 0000 0000 0000 0000  !vL.............
0001ff0: 0100 0100 0208 1800 0d72 6f77 2031 0000  .........row 1..

刪除和真空:

delete from foo where bar='row 1';
vacuum stack.foo;
checkpoint;

表支持文件的物理內容:

xxd -a /var/lib/postgresql/9.3/main/base/12035/446488

0000000: 3800 0000 e8b5 9e83 0000 0500 2000 e01f  8........... ...
0000010: 0020 0420 0000 0000 0000 0000 e09f 3c00  . . ..........<.
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
0001fc0: 2176 4c14 0000 0000 0000 0000 0000 0000  !vL.............
0001fd0: 0200 0100 0209 1800 0d72 6f77 2032 0000  .........row 2.. <---- this is free space
0001fe0: 2176 4c14 0000 0000 0000 0000 0000 0000  !vL.............
0001ff0: 0200 0100 0209 1800 0d72 6f77 2032 0000  .........row 2..

插入新行:

insert into stack.foo(bar) values('row 3');
checkpoint;

表支持文件的最終物理內容:

xxd -a /var/lib/postgresql/9.3/main/base/12035/446488

0000000: 3800 0000 c8ec 9e83 0000 0100 2000 c01f  8........... ...
0000010: 0020 0420 0000 0000 c09f 3c00 e09f 3c00  . . ......<...<.
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
*
0001fc0: 2476 4c14 0000 0000 0000 0000 0000 0000  $vL.............
0001fd0: 0100 0100 0208 1800 0d72 6f77 2033 0000  .........row 3.. <---- this is row 3
0001fe0: 2176 4c14 0000 0000 0000 0000 0000 0000  !vL.............
0001ff0: 0200 0100 0209 1800 0d72 6f77 2032 0000  .........row 2..

清理:

drop schema stack cascade;

引用自:https://dba.stackexchange.com/questions/66188