声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了《PostgresSQL数据库内核分析》一书,OpenGauss1.1.0 的开源代码和《OpenGauss数据库源码解析》一书以及OpenGauss社区学习文档
default_reloptions 函数是一个选项解析器,用于处理与数据库关系(表或视图)相关的选项。它接受一个包含关系选项的参数,然后解析和验证这些选项,将它们存储在一个特定的数据结构中(StdRdOptions)。这个函数的主要目的是允许用户或数据库管理员通过选项来自定义和配置关系的各种属性和行为,例如填充因子、自动化清理策略、安全性设置等。它是数据库系统中对关系配置的重要组成部分,以实现更好的性能和行为控制。
default_reloptions 函数的作用是接收传入的关系选项(以二进制形式表示),然后将这些选项解析和验证,最后将它们存储在一个特定的数据结构(StdRdOptions)中,以便在数据库系统中配置和管理关系的各种属性和行为,如填充因子、自动化清理策略、安全性设置等。这个函数允许数据库管理员或应用程序开发人员根据需要自定义和配置关系的行为和性能特性。
default_reloptions 函数源码如下所示:(路径:src/gausskernel/storage/access/common/reloptions.cpp
)
/*
* 为使用StdRdOptions的任何内容(例如fillfactor和autovacuum)提供选项解析器
* reloptions:传入的关系选项,以二进制形式表示
* validate:指示是否进行验证的标志
* kind:关系选项的类型,通常是RELOPT_KIND_HEAP或RELOPT_KIND_TOAST
*/
bytea *default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
{
relopt_value *options = NULL; // 存储解析后的选项值的数组
StdRdOptions *rdopts = NULL; // 存储最终结果的数据结构
int numoptions; // 选项数量
static const relopt_parse_elt tab[] = {
// 定义选项名称、类型和存储位置的映射数组
// 每个元素包括选项名称、数据类型和在StdRdOptions结构中的偏移量
// 用于将选项值解析到对应的字段中
// 更多选项可以在这里添加
{ "fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor) },
{ "autovacuum_enabled", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled) },
{ "autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold) },
{ "autovacuum_analyze_threshold", RELOPT_TYPE_INT,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold) },
{ "autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay) },
{ "autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit) },
{ "autovacuum_freeze_min_age", RELOPT_TYPE_INT64,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age) },
{ "autovacuum_freeze_max_age", RELOPT_TYPE_INT64,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age) },
{ "autovacuum_freeze_table_age", RELOPT_TYPE_INT64,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age) },
{ "autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor) },
{ "autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor) },
{ "security_barrier", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, security_barrier) },
{ "enable_rowsecurity", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, enable_rowsecurity) },
{ "force_rowsecurity", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, force_rowsecurity) },
{ "enable_tsdb_delta", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, enable_tsdb_delta) },
{ "tsdb_deltamerge_interval", RELOPT_TYPE_INT, offsetof(StdRdOptions, tsdb_deltamerge_interval) },
{ "tsdb_deltamerge_threshold", RELOPT_TYPE_INT, offsetof(StdRdOptions, tsdb_deltamerge_threshold) },
{ "tsdb_deltainsert_threshold", RELOPT_TYPE_INT, offsetof(StdRdOptions, tsdb_deltainsert_threshold) },
{ "max_batchrow", RELOPT_TYPE_INT, offsetof(StdRdOptions, max_batch_rows) },
{ "deltarow_threshold", RELOPT_TYPE_INT, offsetof(StdRdOptions, delta_rows_threshold) },
{ "partial_cluster_rows", RELOPT_TYPE_INT, offsetof(StdRdOptions, partial_cluster_rows) },
{ "internal_mask", RELOPT_TYPE_INT, offsetof(StdRdOptions, internalMask) },
{ "orientation", RELOPT_TYPE_STRING, offsetof(StdRdOptions, orientation) },
{ "compression", RELOPT_TYPE_STRING, offsetof(StdRdOptions, compression) },
{"table_access_method", RELOPT_TYPE_STRING, offsetof(StdRdOptions, table_access_method)},
{ "ttl", RELOPT_TYPE_STRING, offsetof(StdRdOptions, ttl) },
{ "period", RELOPT_TYPE_STRING, offsetof(StdRdOptions, period) },
{ "string_optimize", RELOPT_TYPE_STRING, offsetof(StdRdOptions, string_optimize) },
{ "partition_interval", RELOPT_TYPE_STRING, offsetof(StdRdOptions, partition_interval) },
{ "time_column", RELOPT_TYPE_STRING, offsetof(StdRdOptions, time_column) },
{ "ttl_interval", RELOPT_TYPE_STRING, offsetof(StdRdOptions, ttl_interval) },
{ "gather_interval", RELOPT_TYPE_STRING, offsetof(StdRdOptions, gather_interval) },
{ "version", RELOPT_TYPE_STRING, offsetof(StdRdOptions, version) },
{ "compresslevel", RELOPT_TYPE_INT, offsetof(StdRdOptions, compresslevel) },
{ "ignore_enable_hadoop_env", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, ignore_enable_hadoop_env) },
{ "append_mode", RELOPT_TYPE_STRING, offsetof(StdRdOptions, append_mode) },
{ "merge_list", RELOPT_TYPE_STRING, offsetof(StdRdOptions, merge_list) },
{ "rel_cn_oid", RELOPT_TYPE_INT, offsetof(StdRdOptions, rel_cn_oid) },
{ "append_mode_internal", RELOPT_TYPE_INT, offsetof(StdRdOptions, append_mode_internal) },
{ "start_ctid_internal", RELOPT_TYPE_STRING, offsetof(StdRdOptions, start_ctid_internal) },
{ "end_ctid_internal", RELOPT_TYPE_STRING, offsetof(StdRdOptions, end_ctid_internal) },
{ "user_catalog_table", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, user_catalog_table) },
{ "hashbucket", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, hashbucket) },
{ "primarynode", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, primarynode) },
{ "on_commit_delete_rows", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, on_commit_delete_rows)},
{ "wait_clean_gpi", RELOPT_TYPE_STRING, offsetof(StdRdOptions, wait_clean_gpi)}
};
// 解析传入的关系选项,将其存储在options数组中,并返回选项数量
options = parseRelOptions(reloptions, validate, kind, &numoptions);
/* if none set, we're done */
// 如果没有设置任何选项,则返回NULL
if (numoptions == 0)
return NULL;
// 为rdopts分配内存,根据StdRdOptions结构的大小以及选项数量
rdopts = (StdRdOptions *)allocateReloptStruct(sizeof(StdRdOptions), options, numoptions);
// 使用解析后的选项填充rdopts结构,将选项值分配到对应的字段中
fillRelOptions((void *)rdopts, sizeof(StdRdOptions), options, numoptions, validate, tab, lengthof(tab));
// 释放options数组中的字符串值的内存
for (int i = 0; i < numoptions; i++) {
if (options[i].gen->type == RELOPT_TYPE_STRING && options[i].isset)
pfree(options[i].values.string_val);
}
pfree(options);
// 返回结果,以bytea类型的数据返回StdRdOptions结构
return (bytea *)rdopts;
}
其中,表(或关系)的选项的配置如下表所示:
参 数 | 含 义 |
---|---|
fillfactor | 设置表的填充因子,用于指定在表的数据页中保留多少空间,以便将来插入新行。 |
autovacuum_enabled | 一个布尔值,指定是否启用了自动化清理和分析。 |
autovacuum_vacuum_threshold | 自动清理操作的触发阈值,当表中的行数超过此阈值时,将执行自动清理操作。 |
autovacuum_analyze_threshold | 自动分析操作的触发阈值,当表中的行数超过此阈值时,将执行自动分析操作。 |
autovacuum_vacuum_cost_delay | 自动清理操作的成本延迟,以控制其执行速度。 |
autovacuum_vacuum_cost_limit | 自动清理操作的成本限制,以控制资源消耗。 |
autovacuum_freeze_min_age | 触发自动冻结的最小年龄,用于维护事务ID冻结的表。 |
autovacuum_freeze_max_age | 触发自动冻结的最大年龄,用于维护事务ID冻结的表。 |
autovacuum_freeze_table_age | 自动冻结表的年龄,用于维护事务ID冻结的表。 |
autovacuum_vacuum_scale_factor | 自动清理的比例因子。 |
autovacuum_analyze_scale_factor | 自动分析的比例因子。 |
security_barrier | 一个布尔值,指定是否启用了安全屏障。 |
enable_rowsecurity | 一个布尔值,指定是否启用了行级安全性。 |
force_rowsecurity | 一个布尔值,指定是否强制启用了行级安全性。 |
enable_tsdb_delta | 一个布尔值,指定是否启用了时序数据库(TSDB)的增量数据存储。 |
tsdb_deltamerge_interval | TSDB增量数据合并的时间间隔。 |
tsdb_deltamerge_threshold | TSDB增量数据合并的阈值。 |
tsdb_deltainsert_threshold | TSDB增量数据插入的阈值。 |
max_batchrow | 最大批量行数。 |
deltarow_threshold | 增量行的阈值。 |
partial_cluster_rows | 部分聚集行的数量。 |
internal_mask | 内部掩码。 |
orientation | 表的方向。 |
compression | 数据的压缩方式。 |
table_access_method | 表的访问方法。 |
ttl | 表的生存时间。 |
period | 表的周期。 |
string_optimize | 字符串优化。 |
partition_interval | 分区间隔。 |
time_column | 时间列。 |
ttl_interval | 生存时间间隔。 |
gather_interval | 聚集间隔。 |
version | 版本。 |
compresslevel | 压缩级别。 |
ignore_enable_hadoop_env | 是否忽略启用Hadoop环境。 |
append_mode | 附加模式。 |
merge_list | 合并列表。 |
rel_cn_oid | 关系CN OID。 |
append_mode_internal | 内部附加模式。 |
start_ctid_internal | 内部起始CTID。 |
end_ctid_internal | 内部结束CTID。 |
user_catalog_table | 是否为用户目录表。 |
hashbucket | 是否为哈希桶。 |
primarynode | 是否为主节点。 |
on_commit_delete_rows | 提交时删除行。 |
wait_clean_gpi | 等待清理GPI。 |
这些选项配置了表的各种属性和行为,以满足特定的数据库需求。
接下来,我们通过几个案例来观察其中的几个代表参数的实际作用,来了解一下这些参数的意义。具体案例如下:
1. 创建存储表,执行以下 SQL 语句:
CREATE TABLE test_table (
id serial PRIMARY KEY,
name text
) WITH (
fillfactor = 70, -- 设置填充因子
autovacuum_enabled = true, -- 启用自动清理和分析
autovacuum_vacuum_threshold = 1000, -- 自动清理触发阈值
autovacuum_analyze_threshold = 500, -- 自动分析触发阈值
autovacuum_vacuum_cost_delay = 10, -- 自动清理成本延迟
autovacuum_vacuum_cost_limit = 1000, -- 自动清理成本限制
compression = 'lz4' -- 数据压缩方式
);
postgres=# \d+ test_table
Table "public.test_table"
Column | Type | Modifiers | Storage | Stats target | Description
--------+---------+---------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('test_table_id_seq'::regclass) | plain | |
name | text | | extended | |
Has OIDs: no
Options: orientation=column, autovacuum_enabled=true, autovacuum_analyze_threshold=500, compression=low
2. 插入一些示例数据到列存储表中:
DO $$
DECLARE
counter INT := 1;
BEGIN
FOR counter IN 1..1500 LOOP
INSERT INTO test_table (name) VALUES ('Item ' || counter);
END LOOP;
END $$;
postgres=# select * from test_table;
id | name
------+-----------
1 | Item 1
2 | Item 2
3 | Item 3
4 | Item 4
5 | Item 5
6 | Item 6
7 | Item 7
8 | Item 8
9 | Item 9
10 | Item 10
11 | Item 11
12 | Item 12
13 | Item 13
14 | Item 14
15 | Item 15
16 | Item 16
17 | Item 17
18 | Item 18
19 | Item 19
20 | Item 20
21 | Item 21
22 | Item 22
23 | Item 23
24 | Item 24
25 | Item 25
26 | Item 26
27 | Item 27
28 | Item 28
29 | Item 29
30 | Item 30
31 | Item 31
32 | Item 32
33 | Item 33
34 | Item 34
35 | Item 35
36 | Item 36
37 | Item 37
38 | Item 38
39 | Item 39
--More--
3. 执行自动分析并查看统计信息:
SELECT schemaname,
relname,
last_vacuum,
last_autovacuum,
last_analyze,
last_autoanalyze,
vacuum_count,
autovacuum_count,
analyze_count,
autoanalyze_count
FROM pg_stat_all_tables
WHERE relname = 'test_table';
schemaname | relname | last_vacuum | last_autovacuum | last_analyze | last_autoanalyze | vacuum_count | autovacuum_count | anal
yze_count | autoanalyze_count
------------+------------+-------------+-----------------+-------------------------------+-------------------------------+--------------+------------------+-----
----------+-------------------
public | test_table | | | 2023-10-07 11:32:20.377228+08 | 2023-10-07 11:32:20.377228+08 | 0 | 0 |
1 | 1
(1 row)
可以看到,当表中的数据量达到自动分触发阈值时 autovacuum_analyze_threshold ,则会执行自动分析 autoanalyze。
4. 执行自动清理:
在PostgreSQL数据库中,自动触发autovacuum_vacuum_threshold选项所定义的自动清理(autovacuum)操作通常由数据库自身的内部机制控制。autovacuum_vacuum_threshold是一个配置选项,它定义了当表中的行数达到指定阈值时,自动触发VACUUM操作的条件。
要触发自动清理,需要满足以下条件:
- 表的行数超过了autovacuum_vacuum_threshold所定义的阈值。
- 自动清理(autovacuum)进程处于活动状态,通常是后台运行的自动清理进程。
自动清理进程会定期检查表的状态并根据一系列配置选项来决定是否执行VACUUM操作。autovacuum_vacuum_threshold只是其中之一。其他配置选项还包括autovacuum_analyze_threshold、autovacuum_freeze_max_age等,它们影响了自动清理的行为。
需要注意的是,autovacuum进程通常会在数据库空闲时执行自动清理操作,以避免干扰正在进行的活动查询和事务。此外,autovacuum的行为也可以通过其他配置选项进行微调,以满足特定应用场景的需求。
总之,要触发autovacuum_vacuum_threshold自动清理,需要确保表的行数达到了指定阈值,并确保autovacuum进程处于活动状态,它会自动监测并执行相应的清理操作。
SELECT schemaname,
relname,
last_vacuum,
last_autovacuum,
last_analyze,
last_autoanalyze,
vacuum_count,
autovacuum_count,
analyze_count,
autoanalyze_count
FROM pg_stat_all_tables
WHERE relname = 'test_table';
schemaname | relname | last_vacuum | last_autovacuum | last_analyze | last_autoanalyze | vacuum_count | autov
acuum_count | analyze_count | autoanalyze_count
------------+------------+-------------------------------+-----------------+-------------------------------+-------------------------------+--------------+------
------------+---------------+-------------------
public | test_table | 2023-10-07 15:35:41.430136+08 |2023-10-07 15:35:41.430136+08| 2023-10-07 15:32:22.660942+08 | 2023-10-07 15:32:22.660942+08 | 1 |
0 | 2 | 2
(1 row)
这里不一一列举表(或关系)的选项的配置的案例,如需要详细了解可以查询相关手册。