暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

vacuum操作

點點 2024-05-10
709

vacuum主要用于

  1. 清除死元组并对每个活元组进行碎片整理
  2. 删除指向死元组的索引元组
  3. 冻结旧原组的txid
  4. 更新统计信息以及空闲空间、可见性地图

vacuum处理流程

1.获取每个表的信息并获取表的Shared Update Exclusive Lock锁
2.扫描所有页面获取死元组信息,如果存在则移除死元组对应索引元组,对表每一页执行删除死元组并重新分配活元组信息
3.更新fsm空闲空间以及vm可见性地图信息。如果最后一页没有元组则截断该页
4.更新处理相关的统计信息和系统目录
5.删除不必要的文件和clog页面


当前行包含索引,当第2行数据被删除,vacuum后对应索引信息也会被标记为删除,将原来行所占用空间清除,将第3行移动到原本第2行的位置



可见性地图 

提高vacuum效率,可见性地图用于标记哪些被删除行的数据库的id,用于vacuum参考

被删除的行用0表示,没有被删除的行用1表示。当扫描第1个块时发现发现有被标记为0则进行vacuum操作,当扫描第2个块时发现被标记为1,则跳过继续扫描后续的块
 



full  vacuum 操作

当前3个块中每个块只剩下1行数据,如果只是单纯做vacuum操作,那么只是将死元组信息给清除,当做全表扫描时,需要进行多次I/O才能获取到数据
 

而full vacuum操作会对其创建1个新的数据文件,将原有3个块中行迁移到一个新的数据块中,而后释放旧的数据块





如何正确使用FULL VACUUM操作

创建扩展
create extension sys_freespacemap;

create table a(id int,info text,time timestamp);
insert into a select generate_series(1,100000),md5(random()::text),clock_timestamp();


select count(*) as "number pages",sys_size_pretty(cast(avg(avail) as bigint)) as "freespace size",round(100 *avg(avail)/8192,2) as "freespace ratio" from sys_freespace('a');




数据删除后因未对该表做vacuum操作,所以死元组未被删除导致空间无法释放。vacuum操作后数据块中有大量的空闲空间

delete from a where id %10 !=0 or id <100;




而为了减少数据块的占用,可使用full vacuum操作进行空间整合,从而提高表扫描的效率




auto vacuum

vacuum操作每分钟执行一次,由参数autovacuum_naptime控制。默认调用3个进行进行工作,由参数autovacuum_max_workers控制


auto vacuum实际操作分为2个步骤,分别是vacuum和analyze

autovacuum  vacuum触发条件:由于大量的更新、删除操作导致表中死元组数超过此有效阈值

autovacuum_vacuum_scale_factor  *  number of tuple +autovacuum_vacuum_threshold

autovacuum  analyze触发条件:自上次以来插入、更新、删除总数超过此阈值的任何表

autovacuum_analyze_scale_factor  *  number of tuple +autovacuum_analyze_threshold


autovacuum操作会导致短期内产生大量的I/O,可设置一些参数来减少对I/O的影响

autovacuum_vacuum_cost_limit:autovacuum可达到的总成本上线。默认-1不做限制,如果是SSD硬盘可以把该值设置为5000-10000,如果是一般带缓存的硬件Raid卡输出的机械硬盘,则设置为1000~2000比较合适。过大会导致I/O瓶颈

autovacuum_vacuum_cost_delay:当一个清理工作达到autovacuum_vacuum_cost_limit上线时,autovacuum将休眠毫秒。默认2ms

vacuum_cost_page_hit:读取已经存在共享缓冲区中且不需要磁盘读取页的成本,默认 1 

vacuum_cost_page_miss:获取不在共享缓冲区中页的成本,默认10

vacuum_cost_page_dirty:在每一页发现死元组时写入该页的成本,默认20

autovacuum_max_workers=3

autovacuum_naptime=1min



在无延迟的情况下,在做autovacuum时1s的工作量时多少 。假设autovacuum_vacuum_cost_limit=200、autovacuum_vacuum_cost_delay=2ms、vacuum_cost_page_hit=1、vacuum_cost_page_miss=10、vacuum_cost_page_dirty=20

1000ms = 500 * autovacuum_vacuum_cost_delay

由于在共享内存每次读取的成本为1,因此每个唤醒中可以读取200个页面。在500个唤醒中可以读取500 * 200个页面
如果在共享内存中找到具有死元组的页,并且autovacuum代价延迟为20ms,则在每一轮读取((200/vacuum_cost_page_hit)* 8)KB
考虑到块大小为8192字节,autovacuum在共享内存中最多可以读取(500 * 200 * 8kb)=781.3mb/s
若块不在共享内存中,需从磁盘读取时,则autovacuum可以读取500 * (200/vacuum_cost_page_miss) * 8)KB =78.1mb/s
为了从页/块中删除死元组,则autovacuum每秒最多写500 * (200/vacuum_cost_page_dirty) * 8)KB =39mb/s


死元组可通过视图sys_stat_user_tables或创建扩展kbstattuple查看

create extension kbstattuple;

select *,1.0 - tuple_len::numeric / table_len as bloat from pgstattuple('a');





















最后修改时间:2024-05-10 18:54:01
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论