vacuum:该选项主要是清理数据库表中的垃圾空间,该动作会消耗系统一定的资源,引起系统的IO上升,对有一定系统瓶颈来说容易造成堵塞,严重会把GP宕掉,造成数据库瞬断。一般不建议vacuum库中全表,通常做法是 vacuum 指定的表。
GPDB 与PostgreSQL一样,在执行delete语句时,并没有将数据删除,而是标志为删。
执行update,只是将旧数据标记为删除,重新再插入一条新数据。
这样如果一张表删改的动作特别多,就会导致体积持续变大,比较浪费磁盘空间。
(delete或update操作的数据不会从真实的物理空间中移除,只是针对目标数据进行了标记,数据还是保留在了磁盘上,这样做只是提升了操作效率。vacuum操作可以将磁盘中的此类空间释放出来,所以对那些经常更新删除的表做vacuum操作很有必要)
例:
- 创建测试表:
CREATE TABLE "public"."vacuum_test" (
"id" int4 NOT NULL,
"name" varchar(255) NOT NULL
);
- 插入测试数据
INSERT INTO vacuum_test select generate_series(1,100000) as id,random() as name;
- 查看表大小:
select pg_relation_size('vacuum_test');
- 然后进行删除操作:
DELETE from vacuum_test;
- 数据已经删除,然后观察磁盘空间。
大小没有变化。
- 重新插入数据。
磁盘空间翻倍
- 更新操作
更新操作后空间继续增长。此时就有一部分空空间为标记的删除数据没有释放。
- vacuum
执行后大小没有变化,空间没有释放么?
是的没有释放,因为刚才操作的空间不是末端数据,只有末端数据vacuum才会归还给操作系统,非末端位置,可以再次写入覆盖。vacuum full可以直接清除归还操作系统。
- 重新插入数据(查看是否能覆盖刚才的空间)
INSERT INTO vacuum_test select generate_series(1,100000) as id,'77777' as name;
是的已经覆盖掉了。
- 再次插入
INSERT INTO vacuum_test select generate_series(1,100000) as id,'88888' as name;
空间增加了。
- 这是删除末端进行测试
DELETE from vacuum_test where name='88888';
然后vacuum 查看空间
空间释放,印证末端问题。