• 【PostgreSQL内核学习(十八)—— (数据库表参数)】


    数据库表参数

    声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
    本文主要参考了《PostgresSQL数据库内核分析》一书,OpenGauss1.1.0 的开源代码和《OpenGauss数据库源码解析》一书以及OpenGauss社区学习文档

    default_reloptions 函数

      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;
    }
    
    • 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
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

      其中,表(或关系)的选项的配置如下表所示:

    参 数含 义
    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_intervalTSDB增量数据合并的时间间隔。
    tsdb_deltamerge_thresholdTSDB增量数据合并的阈值。
    tsdb_deltainsert_thresholdTSDB增量数据插入的阈值。
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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--
    
    • 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

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

      可以看到,当表中的数据量达到自动分触发阈值autovacuum_analyze_threshold ,则会执行自动分析 autoanalyze

    4. 执行自动清理

      在PostgreSQL数据库中,自动触发autovacuum_vacuum_threshold选项所定义的自动清理autovacuum)操作通常由数据库自身的内部机制控制autovacuum_vacuum_threshold是一个配置选项,它定义了当表中的行数达到指定阈值时,自动触发VACUUM操作的条件

    要触发自动清理,需要满足以下条件:

    1. 表的行数超过了autovacuum_vacuum_threshold所定义的阈值
    2. 自动清理(autovacuum)进程处于活动状态,通常是后台运行的自动清理进程

      自动清理进程会定期检查表的状态并根据一系列配置选项来决定是否执行VACUUM操作。autovacuum_vacuum_threshold只是其中之一。其他配置选项还包括autovacuum_analyze_thresholdautovacuum_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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

      这里不一一列举表(或关系)的选项的配置的案例,如需要详细了解可以查询相关手册。

  • 相关阅读:
    洋码头 根据ID取商品详情 API
    「C++」复杂模拟【壹】
    【Linux】awk命令简单用法
    Elasticsearch搜索引擎
    win7系统修改磁盘提示参数错误的解决办法
    常用辅助类
    LiveNVR监控流媒体Onvif/RTSP功能-支持海康摄像头海康NVR通过EHOME协议ISUP协议接入分发视频流或是转GB28181
    彻底搞懂Swagger&Knife4j使用方法
    OBS 安装与考试参数设置及屏幕无法完全捕获、录屏不完整的解决方法
    DoIP通信中的TLS加密
  • 原文地址:https://blog.csdn.net/qq_43899283/article/details/133639772