签到成功

知道了

CNDBA社区CNDBA社区

PostgreSQL Vacuum 说明

2022-12-17 21:55 1215 0 原创 PostgreSQL
作者: dave

1 Vacuum 概念

Vacuum 是PG 为了实现MVCC(多版本并发控制)而采用的一种技术。 不同数据库实现MVCC 方法不一样。 http://www.cndba.cn/dave/article/116401

1.1 Oracle/MySQL

这两种数据库是通过undo日志来实现MVCC。当数据记录被DML修改,将修改前的数据记录在undo log中,客户端可以读取数据时,通过undo log指针进行回滚找到对应可见的版本。

长事物、大事物会导致undo log暴涨,一定程度上会导致系统日志文件磁盘空间占用的暴涨。只有将事物提交/回滚,相关版本记录不再需要时,对应的版本数据才会被清理,undo系统文件空间才会把无效的版本空间进行释放。http://www.cndba.cn/dave/article/116401

1.2 SQL Server

它是通过tempdb数据库来实现的。当数据记录被DML修改,将旧版本数据写入tempdb进行存储,客户端读取数据时,可从通过指针找到tempdb数据库中对应可见的版本。

http://www.cndba.cn/dave/article/116401

长事物、大事物会导致tempdb空间暴涨,只有事物提交,相关版本记录不再需要时,才会将相关的版本记录进行释放,需要注意的是这部分磁盘空间消耗是没有释放给操作系统的,需要手动进行磁盘空间收缩。

1.3 PostgreSQL

通过保留变更前的记录来实现MVCC的。当数据记录被DML修改,旧版本记录仍保留不变,仅仅需要修改相关记录的xmin、xmax属性,并新增写入变更后的版本记录数据。http://www.cndba.cn/dave/article/116401

http://www.cndba.cn/dave/article/116401

由于历史版本数据仍然保留在原表空间中,默认情况下autovacuum会按照一定的参数设置策略检测并进行一定的清理,但频繁的数据变极大可能导致旧版本数据空间来不及进行空间回收,从而导致表空间膨胀。

1.4 MVCC实现方法对比

通过undo log或者tempdb来进行旧版本存储的方式,有效的避免了表空间膨胀,相对于PG直接保留旧版本数据的方式,每次DML操作都需要额外的日志写入,存在一定的IO消耗(目前SSD盘存储下,感觉影响不会很大);http://www.cndba.cn/dave/article/116401

PG这种直接保留旧版本数据的方式,无需额外的日志写入的消耗,但是一定程度上会导致旧版本数据没有及时清理,导致表空间膨胀,影响该表数据的查询效率(扫描了不必要的数据页)。

2 AutoVacuum 配置

2.1 AutoVacuum 参数

autovacuum为PG数据库中可以实现自动vacuum的一个守护进程(postgres: autovacuum launcher),需要数据库将参数autovacuum参数打开。

autovacuum会自动检测发生了大量DML操作的表对象,并对其进行垃圾回收和统计信息的重新采集,相当于手动执行 vacuum analyze 。

http://www.cndba.cn/dave/article/116401

[root@dave ~]# ps -ef|grep postgre
postgres 112702      1  0 20:44 ?        00:00:00 /usr/pgsql-14/bin/postgres -D /data/postgresql/data14
postgres 112703 112702  0 20:44 ?        00:00:00 postgres: logger
postgres 112705 112702  0 20:44 ?        00:00:00 postgres: checkpointer
postgres 112706 112702  0 20:44 ?        00:00:00 postgres: background writer
postgres 112707 112702  0 20:44 ?        00:00:00 postgres: walwriter
postgres 112708 112702  0 20:44 ?        00:00:00 postgres: autovacuum launcher
postgres 112709 112702  0 20:44 ?        00:00:00 postgres: stats collector
postgres 112710 112702  0 20:44 ?        00:00:00 postgres: logical replication launcher
root     123251 122926  0 21:10 pts/4    00:00:00 vim postgresql.conf
root     127476 127335  0 21:20 pts/6    00:00:00 grep --color=auto postgre
[root@dave ~]#

在PG的配置文件中,有一部分是AutoVacuum的配置。

#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------

#autovacuum = on                        # Enable autovacuum subprocess?  'on'
                                        # requires track_counts to also be on.
#autovacuum_max_workers = 3             # max number of autovacuum subprocesses
                                        # (change requires restart)
#autovacuum_naptime = 1min              # time between autovacuum runs
#autovacuum_vacuum_threshold = 50       # min number of row updates before
                                        # vacuum
#autovacuum_vacuum_insert_threshold = 1000      # min number of row inserts
                                        # before vacuum; -1 disables insert
                                        # vacuums
#autovacuum_analyze_threshold = 50      # min number of row updates before
                                        # analyze
#autovacuum_vacuum_scale_factor = 0.2   # fraction of table size before vacuum
#autovacuum_vacuum_insert_scale_factor = 0.2    # fraction of inserts over table
                                        # size before insert vacuum
#autovacuum_analyze_scale_factor = 0.1  # fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000  # maximum XID age before forced vacuum
                                        # (change requires restart)
#autovacuum_multixact_freeze_max_age = 400000000        # maximum multixact age
                                        # before forced vacuum
                                        # (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms     # default vacuum cost delay for
                                        # autovacuum, in milliseconds;
                                        # -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1      # default vacuum cost limit for
                                        # autovacuum, -1 means use
                                        # vacuum_cost_limit

参数说明

1.autovacuum : 是否开启autovacuum守护进程,默认开启
2.log_autovacuum_min_duration : 指定autovacuum执行耗时超过该参数时,将对应操作记录到日志,-1表示禁用autovacuum的日志记录
3.autovacuum_max_workers : autovacuum可启动的最大worker数,默认为3
4.autovacuum_naptime : 指定两次autovacuum之间的时间延迟,默认为1min
5.autovacuum_vacuum_threshold 、autovacuum_vacuum_scale_factor : 指定一张表Delete、Update的tuple数超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_threshold为50,autovacuum_vacuum_scale_factor为20
6.autovacuum_vacuum_insert_threshold 、 autovacuum_vacuum_insert_scale_factor : 指定一张表Insert的tuple数超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum。默认autovacuum_vacuum_insert_threshold为50,autovacuum_vacuum_insert_scale_factor为20
7.autovacuum_analyze_threshold 、autovacuum_analyze_scale_factor : 指定一张表Insert、Delete、Update的tuple数超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作。默认autovacuum_analyze_threshold为50,autovacuum_analyze_scale_factor为20
8.autovacuum_freeze_max_age : 为防止表中事物ID回卷,指定表的最大事物ID(pg_class.relfrozenxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
9.autovacuum_multixact_freeze_max_age : 为防止表中多个事物ID回卷,指定表的最大事物ID(pg_class.relminmxid),超过该参数值自动触发autovacuum,即使autovacuum参数设置为off
10.autovacuum_vacuum_cost_delay : 指定计算autovacuum的代价延迟值
11.autovacuum_vacuum_cost_limit : 指定autovacuum操作的代价限制值

2.2 AutoVacuum 工作原理

根据参数的配置,autovacuum 相关规则如下:

http://www.cndba.cn/dave/article/116401

1.当参数autovacuum设置为on时,数据库会启动一个autovacuum的守护进程,当满足触发条件时启动相关的autovacuum经常进行垃圾回收操作;
2.当表update,delete的tuples数量超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold 时,自动触发autovacuum操作
3.当表insert的tuples数量超过 autovacuum_vacuum_insert_scale_factor * table_size + autovacuum_vacuum_insert_threshold 时,自动触发autovacuum操作
4.当表的insert,delete,update的tuple超过 autovacuum_analyze_scale_factor * table_size + autovacuum_analyze_threshold 时,自动触发analyza操作
5.当表的最大事物ID超过autovacuum_freeze_max_age、autovacuum_multixact_freeze_max_age 时,自动触发autovacuum操作
6.默认两次autovacuum之前的时间间隔为autovacuum_naptime,且每次进行autovacuum时可启动的最大并发数为autovacuum_max_workers

2.3 AutoVacuum 配置

全局参数并不一定适用于所有表,特殊表可在表级别定义相关参数。例如变更频繁的表,可适当减少autovacuum_vacuum_scale_factor、autovacuum_vacuum_threshold参数值,使得其可以及时的垃圾回收,避免表膨胀影响其查询效率。http://www.cndba.cn/dave/article/116401

autovacuum_max_workers可根据操作系统CPU资源进行适当调整。

3 手工执行Vacuum

除了上面说的autovacuum之外,也可以手工执行。

语法如下:

http://www.cndba.cn/dave/article/116401

VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
where option can be one of:

    FULL [ boolean ]
    FREEZE [ boolean ]
    VERBOSE [ boolean ]
    ANALYZE [ boolean ]
    DISABLE_PAGE_SKIPPING [ boolean ]
    SKIP_LOCKED [ boolean ]
    INDEX_CLEANUP { AUTO | ON | OFF }
    PROCESS_TOAST [ boolean ]
    TRUNCATE [ boolean ]
    PARALLEL integer
and table_and_columns is:

    table_name [ ( column_name [, ...] ) ]

参数说明:

VACUUM FULL
执行期间需要获取对应表的独占锁,阻塞其他客户端的读写操作。该模式下会将对应表数据重新写入一个新的表空间文件,最后替换为新的表文件,这种方式下可以回收dead tuple空间并释放给操作系统。该操作执行消耗是比较大的,且耗时的。

VACUUM FREEZE
使用一种激进的方式冻结元祖,相当于把参数 vacuum_freeze_min_age 、 vacuum_freeze_table_age 设置为0。该模式下Full参数指定是多余的,该操作执行消耗同样是比较大的,且耗时的。

VACUUM VERBOSE
执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统,vacuum期间打印每张表详细的垃圾回收记录。

VACUUM ANALYZE
执行期间不需要获取对应表的独占锁,允许其他客户端的并发读写操作,执行完毕vacuum后会再次执行analyza重新采集相关表的统计信息。该模式下仅仅会将dead tuple空间进行回收并释放给数据库,并不会释放给操作系统。

VACUUM INDEX_CLEANUP ON
默认情况下,vacuum会跳过index vacuum, 当INDEX_CLEANUP  设置为ON时,vacuum 在释放表和索引的dead tuple。

更多参数说明参考官方手册:

https://www.postgresql.org/docs/current/sql-vacuum.html

使用示例:

[dave@www.cndba.cn data14]# su - postgres
Last login: Sat Dec 17 16:31:55 CST 2022 on pts/3
-bash-4.2$ psql
psql (14.6)
Type "help" for help.

postgres=# /c cndba
You are now connected to database "cndba" as user "postgres".

cndba=# vacuum (analyze,verbose,index_cleanup on) dave;
INFO:  vacuuming "public.dave"
INFO:  table "dave": found 0 removable, 1 nonremovable row versions in 1 out of 1 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 872
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO:  analyzing "public.dave"
INFO:  "dave": scanned 1 of 1 pages, containing 1 live rows and 0 dead rows; 1 rows in sample, 1 estimated total rows
VACUUM
cndba=#

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
dave

dave

关注

人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业....."

  • 2261
    原创
  • 3
    翻译
  • 578
    转载
  • 191
    评论
  • 访问:7971653次
  • 积分:4346
  • 等级:核心会员
  • 排名:第1名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ