在PostgreSQL,吸尘是维护任务,帮助优化数据库性能和回收空间。它涉及删除删除或过时的行从表和索引和更新统计信息使用的查询计划。这个过程是必要的,以防止不必要的数据的积累,被称为“死亡”行,可以将重要的空间和减缓查询。
多版本并发控制(MVCC)
保持一致性和防止数据丢失由于并发更新,PostgreSQL雇用了多版本并发控制(MVCC)。PostgreSQL和其他数据库管理系统使用MVCC确保一致的读取,防止数据丢失的并发更新。PostgreSQL是通过存储多个版本的数据库中的每一行,允许事务访问一个一致的数据快照。
在PostgreSQL,表中的每一行被赋予一个事务ID被称为一个“xmin”。这个ID标志着事务插入的行。当一行被更新或者删除,没有立即从表中删除。相反,一个新版本的行插入一个新的事务ID,而旧版本与事务ID标记为“死亡”称为“xmax”。
当一个事务读取一行,它利用xmin和xmax值来确定事务的行是可见的。如果xmin值大于事务的“快照”(一个记录的事务id在事务开始时进展),事务的行是不可见的。如果xmax值等于事务ID,行已被删除的交易,也是不可见的。在所有其他情况下,行是可见的事务。
这允许事务访问一个一致的数据快照,他们只能看到行提交事务开始时。它还可以防止数据丢失由于并发更新,由于冲突的更新在插入新行版本而不是覆盖现有数据。
尽管MVCC会引入一些开销存储和性能而言,由于需要维护多个版本的每一行,这是一个至关重要的特点PostgreSQL和其他支持的并发更新的数据库系统。
这允许多个版本的每一行存储,使交易能够访问一个一致的数据快照。然而,这可能导致死亡的累积行是行被更新或者删除。
吸尘
PostgreSQL的真空过程有助于保持数据库的性能和空间效率通过移除不再需要的行。
这些行,被称为“死行,”积累因为PostgreSQL使用MVCC允许多个事务同时访问相同的数据没有冲突。在真空的过程中,表和索引扫描,这些死行删除,帮助回收空间和提高查询性能。必须运行一个真空保持数据库定期平稳运行。MVCC存储多个版本的每一行,所以死行不会立即删除当一行被更新或者删除。
真空过程删除死行和更新统计数据所使用的查询计划更准确地估计由一个查询返回的行数,选择最有效的执行计划。有两种类型的真空在PostgreSQL:真空和分析。真空除去死行和更新统计数据,分析仅更新统计数据。一般建议两个真空和分析一起运行。
真空过程可以使用SQL命令手动启动或自动使用autovacuum后台进程运行基于可配置的阈值如死去的行数或生活一个表中的记录。在PostgreSQL 15,真空过程进行了优化,使之更有效和快速真空大表。它包括改进真空能力等多个分区并行的表,同时真空索引,索引和跳过吸尘不受一个更新的影响。
从技术角度来看,PostgreSQL 15中的真空过程涉及多个组件。真空守护进程(autovacuum)启动真空操作基于可配置的阈值。真空工人执行实际的真空操作,扫描表或索引和去除死行,并更新统计数据。
Autovacuum,默认启用在PostgreSQL和可以使用PostgreSQL中几个参数配置。conf文件。PostgreSQL有几个设置相关的真空,可以配置为控制真空流程运行的方式。你可以找到以下设置postgresql。配置文件,包括:
- autovacuum:这个设置启用或禁用autovacuum后台进程。默认情况下,启用autovacuum。
- autovacuum_vacuum_threshold:此设置确定最小数量的死亡之前必须存在于一个表的行是真空的。默认值为50。
- autovacuum_analyze_threshold:此设置确定最小数量的住行必须出现在一个表之前,进行了分析。默认值为50。
- autovacuum_vacuum_scale_factor:这个设置是一个乘数决定有多少死行需要触发真空基于表的大小。默认值是0.2。
- autovacuum_analyze_scale_factor:这个设置是一个乘数决定有多少住行需要触发一个分析基于表的大小。默认值是0.1。
- autovacuum_vacuum_cost_delay:此设置确定时间(以毫秒为单位)autovacuum将开始前等待真空操作。默认值是20。
- autovacuum_vacuum_cost_limit:此设置确定的最大行数可以用吸尘器清扫在一个真空操作。默认值是200。
这里是一个例子配置中的一些真空设置postgresql。配置文件:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
autovacuum
=<年代pan class="crayon-h">
在
autovacuum_vacuum_threshold
=<年代pan class="crayon-h">
One hundred.
autovacuum_analyze_threshold
=<年代pan class="crayon-h">
One hundred.
autovacuum_vacuum_scale_factor
=<年代pan class="crayon-h">
0.5
autovacuum_analyze_scale_factor
=<年代pan class="crayon-h">
0.2
autovacuum_vacuum_cost_delay
=<年代pan class="crayon-h">
50
autovacuum_vacuum_cost_limit
=<年代pan class="crayon-h">
500年
|
在这个例子中,autovacuum启用,真空和分析的阈值设置为100。真空的规模因素和分析将0.5和0.2,分别,这意味着一个真空将被触发时50死行每1000个活行表中(0.5 x 100),和一个分析时将触发有20个住行表中每1000行(0.2×100)。真空延迟设置为50毫秒,成本和真空成本限制设置为500行,这意味着autovacuum会等待50毫秒真空操作开始前,将真空最多500行。
配置这些设置是很重要的,确保真空和分析正确有效地运行,而不是造成太多的数据库上的负载。也是一个好主意监控autovacuum和手动真空表的raybet雷竞技竞猜在线官网活动不充分autovacuum维护的。
Autovacuum也可以配置在表的基础上使用autovacuum_vacuum_cost_delay和autovacuum_vacuum_cost_limit参数在表的存储参数。这些参数控制如何积极autovacuum真空表,成本较低延迟导致真空运行更频繁和更高的成本限制允许更多的行用吸尘器吸尘。
平行吸尘
并行真空是PostgreSQL的特性允许将真空处理并发运行多个核心或处理器,提高真空操作的性能。这对吸尘大型表可以特别有用,因为它允许真空过程使用多个cpu并行扫描和处理表。
PostgreSQL 13中的平行介绍了真空作为实验功能,一般可在PostgreSQL 14。使用一个平行的空间,您需要设置postgresql的“max_parallel_workers_per_gather”参数。conf配置文件值大于1。要启用并行处理,指定“平行”选项在运行真空或分析命令。
例如,运行一个平行的真空表名为“foo_table”,您可以使用以下命令:
|
1
|
真空
(
平行
,
分析
)
foo_table
;
|
您还可以指定“平行”选项在运行真空或分析命令整个模式或数据库:
|
1
|
真空
(
平行
,
分析
)
schema_name
。*<年代pan class="crayon-sy">;
真空
(
平行
,
分析
)
;
|
注意:请记住,平行真空可以增加数据库服务器上的负载,因为它需要同时使用多个CPU核。你应该仔细监视数据库的性能在使用一个平行的raybet雷竞技竞猜在线官网真空和调整“max_parallel_workers_per_gather”参数,需要找到最优设置为您的工作负载。
事务的
交易的是一种现象,可以发生在PostgreSQL的最大事务ID (TXID)已经达到,和系统封装在重用旧的事务ID。这会产生问题如果还有行数据库中的事务ID高于当前最大,因为他们将被认为是“死亡”,通过真空过程。
理解transaction-wraparound是如何工作的,有必要了解PostgreSQL管理事务id。PostgreSQL事务被分配一个惟一的事务ID被称为“xid。“xid是一个32位整数,这意味着它有一个最大值2 ^ 32-1,或4294967295年。当达到这个最大值时,系统封装和重用旧的xid。
阻止交易的造成的问题,是很重要的定期运行真空处理和删除死行。可以使用以下查询事务概括的风险检查表。
真空统计
真空历史观为当前模式中的所有表:
该查询检索真空统计所有表的“公共”模式在当前的数据库。该查询可以帮助监测真空处理和识别的状态表raybet雷竞技竞猜在线官网,可能需要用吸尘器清扫或分析。例如,如果一个表有很多死行或没有真空的最近分析了。在这种情况下,它可能值得运行手动真空或分析操作来提高数据库的性能。
|
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61年
62年
63年
64年
65年
66年
67年
|
选择
n
.nspname
作为
schema_name
,
c
.relname
作为
table_name
,
c
.reltuples
作为
row_count
,
c
.relpages
作为
page_count
,
年代
.n_dead_tup
作为
dead_row_count
,
年代
.last_vacuum
,
年代
.last_autovacuum
,
年代
.last_analyze
,
年代
.last_autoanalyze
从
pg_class
c
加入
pg_namespace
n
在
n
.oid
=<年代pan class="crayon-h">
c
.relnamespace
左
加入
pg_stat_user_tables
年代
在
年代
.relid
=<年代pan class="crayon-h">
c
.oid
在哪里
c
.relkind
=<年代pan class="crayon-h">
“r”
和
n
.nspname
=<年代pan class="crayon-h">
“公共”
;
- - - - - -<年代pan class="crayon-sy">(
记录
1
]- - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
schema_name
|
公共
table_name
|
pgbench_accounts
row_count
|
9.999965 e+<年代pan class="crayon-cn">06
page_count
|
163935年
dead_row_count
|
41705年
last_vacuum
|
2022年- - - - - -<年代pan class="crayon-cn">12- - - - - -<年代pan class="crayon-cn">25
16
:
00
:
36.231734+<年代pan class="crayon-cn">00
last_autovacuum
|
last_analyze
|
2022年- - - - - -<年代pan class="crayon-cn">12- - - - - -<年代pan class="crayon-cn">25
16
:
00
:
18.90299+<年代pan class="crayon-cn">00
last_autoanalyze
|
- - - - - -<年代pan class="crayon-sy">(
记录
2
]- - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
schema_name
|
公共
table_name
|
pgbench_branches
row_count
|
One hundred.
page_count
|
1
dead_row_count
|
41
last_vacuum
|
2022年- - - - - -<年代pan class="crayon-cn">12- - - - - -<年代pan class="crayon-cn">25
16
:
00
:
44.722317+<年代pan class="crayon-cn">00
last_autovacuum
|
last_analyze
|
2022年- - - - - -<年代pan class="crayon-cn">12- - - - - -<年代pan class="crayon-cn">25
16
:
00
:
16.254529+<年代pan class="crayon-cn">00
last_autoanalyze
|
2022年- - - - - -<年代pan class="crayon-cn">12- - - - - -<年代pan class="crayon-cn">25
16
:
01
:
45.957663+<年代pan class="crayon-cn">00
|
查看表的列表,修改自上次真空:
|
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
|
选择
n
.nspname
作为
schema_name
,
c
.relname
作为
table_or_index_name
,
c
.relkind
作为
table_or_index
,
c
.reltuples
作为
row_count
,
年代
.last_vacuum
,
年代
.last_autovacuum
,
年代
.last_analyze
,
年代
.last_autoanalyze
从
pg_class
c
加入
pg_namespace
n
在
n
.oid
=<年代pan class="crayon-h">
c
.relnamespace
左
加入
pg_stat_user_tables
年代
在
年代
.relid
=<年代pan class="crayon-h">
c
.oid
在哪里
(
c
.relkind
=<年代pan class="crayon-h">
“r”
或
c
.relkind
=<年代pan class="crayon-h">
“我”
)
和
(
年代
.last_vacuum
<
年代
.last_autovacuum
或
年代
.last_vacuum
<
年代
.last_analyze
)
;
|
查看表和索引的列表,有一个高的行数:
|
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
44
45
46
47
48
49
50
51
52
53
54
55
56
|
选择
n
.nspname
作为
schema_name
,
c
.relname
作为
table_name
,
c
.reltuples
作为
row_count
,
年代
.n_dead_tup
作为
dead_row_count
从
pg_class
c
加入
pg_namespace
n
在
n
.oid
=<年代pan class="crayon-h">
c
.relnamespace
左
加入
pg_stat_user_tables
年代
在
年代
.relid
=<年代pan class="crayon-h">
c
.oid
在哪里
c
.relkind
=<年代pan class="crayon-h">
“r”
和
年代
.n_dead_tup
>
0
;
选择
n
.nspname
作为
schema_name
,
c
.relname
作为
index_name
,
年代
.n_dead_tup
作为
dead_row_count
从
pg_class
c
加入
pg_namespace
n
在
n
.oid
=<年代pan class="crayon-h">
c
.relnamespace
左
加入
pg_stat_user_tables
年代
在
年代
.relid
=<年代pan class="crayon-h">
c
.oid
在哪里
(
c
.relkind
=<年代pan class="crayon-h">
”
r
”
或
c
.relkind
=<年代pan class="crayon-h">
”
我
”
)
和
(
年代
.last_vacuum
<
年代
.last_autovacuum
或
年代
.last_vacuum
<
年代
.last_analyze
)”<年代pan class="crayon-sy">)
作为
t
(
schema_name
文本
,
table_or_index_name
文本
,
table_or_index
字符
(
1
)
,
row_count
长整型数字
,
last_vacuum
时间戳
,
last_autovacuum
时间戳
,
last_analyze
时间戳
,
last_autoanalyze
时间戳
)
;
|
您可以编写使用dblink上面的查询的数据库。这将给所有数据库的信息。
|
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
44
45
46
47
48
49
|
选择
*
从
dblink
(
“主机= <主机>端口= <口> dbname = <数据库>用户= <用户名>密码= <密码> '
,
”<年代pan class="crayon-i">选择
n
.nspname
作为
schema_name
,
c
.relname
作为
table_or_index_name
,
c
.relkind
作为
table_or_index
,
c
.reltuples
作为
row_count
,
年代
.last_vacuum
,
年代
.last_autovacuum
,
年代
.last_analyze
,
年代
.last_autoanalyze
从
pg_class
c
加入
pg_namespace
n
在
n
.oid
=<年代pan class="crayon-h">
c
.relnamespace
左
加入
pg_stat_user_tables
年代
在
年代
.relid
=<年代pan class="crayon-h">
c
.oid
在哪里
(
c
.relkind
=<年代pan class="crayon-h">
”
r
”
或
c
.relkind
=<年代pan class="crayon-h">
”
我
”
)
和
(
年代
.last_vacuum
<
年代
.last_autovacuum
或
年代
.last_vacuum
<
年代
.last_analyze
)”<年代pan class="crayon-sy">)
作为
t
(
schema_name
文本
,
table_or_index_name
文本
,
table_or_index
字符
(
1
)
,
row_count
长整型数字
,
last_vacuum
时间戳
,
last_autovacuum
时间戳
,
last_analyze
时间戳
,
last_autoanalyze
时间戳
)
;
|
注意:你需要替换占位符<主机>、<口>,<数据库>、<用户名>和<密码>为您的服务器与实际值。
结论
重要的是要正确配置autovacuum避免重载数据库与太多的真空吸尘器。也是一个好主意监控autovacuum和手动真空表的raybet雷竞技竞猜在线官网活动不充分autovacuum维护的。
总之,在PostgreSQL吸尘是一个重要的维护任务,有助于回收空间和提高性能。t是一般建议定期运行真空,使用真空SQL命令手动或自动使用autovacuum后台进程。这有助于确保数据库仍然是有效的和自由的死行和降低了交易的风险。Autovacuum自动化这个过程是一种方便的方法,但重要的是配置和监控,以确保它运行有效和充分。raybet雷竞技竞猜在线官网






