【OpenGauss源码学习 —— (ALTER TABLE(调整表中特定列的统计目标))】

ALTER TABLE(调整表中特定列的统计目标)

  • [ATExecAddStatistics 函数](#ATExecAddStatistics 函数)
    • [es_get_starelkind 和 es_get_stainherit 函数](#es_get_starelkind 和 es_get_stainherit 函数)
    • [es_build_vacattrstats_array 函数](#es_build_vacattrstats_array 函数)

声明 :本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。

本文主要参考了 OpenGauss5.1.0 的开源代码和《OpenGauss数据库源码解析》一书

ALTER TABLE ... ALTER COLUMN ... SET STATISTICS 命令用于调整数据库表中特定列的统计目标,以优化查询性能。通过设置列的统计信息 ,数据库查询优化器能够更准确地估算查询结果的选择性,从而生成更高效的查询计划。在 OpenGauss 中,ATExecAddStatistics 函数负责执行这一操作,确保新统计信息的正确应用和存储,从而提高数据库的整体性能和效率。

ATExecAddStatistics 函数

函数ATExecAddStatistics 用于为表添加统计信息,以便优化查询性能。其主要功能包括:

  1. 检查输入参数: 首先确保 def 参数是一个列表。
  2. 获取表的 OID: 从关系对象中获取表的 OID ,并检查是否为系统目录表。如果是系统目录表,报告错误,因为系统目录不支持扩展统计信息。
  3. 获取关系类型和继承标志: 获取关系的类型和是否继承的标志,用于后续的统计信息处理。
  4. 构建 VacAttrStats 数组: 通过调用 es_build_vacattrstats_array 函数,构建包含列统计信息的 VacAttrStats 数组。
  5. 更新属性统计信息: 如果数组长度大于 0 ,调用 update_attstats 函数更新表的属性统计信息。

通过这些步骤,ATExecAddStatistics 函数确保表的统计信息能够正确添加和更新,从而优化查询性能并提高数据库的整体效率。详细代码描述如下所示:(路径:src\gausskernel\optimizer\commands\tablecmds.cpp

cpp 复制代码
/*
 * ATExecAddStatistics
 *     执行添加统计信息操作
 *
 * @param (in) rel:
 *     关系(表)
 * @param (in) def:
 *     修改表列定义
 * @param (in) lockmode:
 *     锁模式
 */
static void ATExecAddStatistics(Relation rel, Node* def, LOCKMODE lockmode)
{
    Assert(IsA(def, List)); // 确保def是一个列表

    Oid relid = rel->rd_id; // 获取关系的OID
    if (is_sys_table(relid)) {
        ereport(ERROR,
            ((errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                errmsg("System catalog is not supported by extended statistic.")))); // 系统目录不支持扩展统计信息
    }

    char relkind = es_get_starelkind(); // 获取关系的类型
    bool inh = es_get_stainherit(); // 获取是否继承的标志

    /* VacAttrStats列表 */
    int array_length = 0; // 初始化VacAttrStats数组长度
    VacAttrStats** vacattrstats_array = es_build_vacattrstats_array(rel, (List*)def, true, &array_length, inh); // 构建VacAttrStats数组

    if (array_length > 0) {
        update_attstats(relid, relkind, false, array_length, vacattrstats_array, RelationGetRelPersistence(rel)); // 更新属性统计信息
    }
}

es_get_starelkind 和 es_get_stainherit 函数

函数 es_get_starelkindes_get_stainherit 是两个简单的辅助函数,用于返回预定义的常量值。具体来说:

  1. es_get_starelkind: 此函数返回一个表示通用 starelkind 的字符常量。在当前实现中,它返回 STARELKIND_CLASS ,通常表示数据库中的类(视图等)。
  2. es_get_stainherit: 此函数返回一个布尔值,指示通用的继承属性。在当前实现中,它返回 false,表示不支持继承。

这两个函数通常用于统计信息管理或表属性查询的上下文中,为调用者提供默认的或通用的 starelkindstainherit 值,从而简化其他函数中的逻辑处理。(src\gausskernel\optimizer\commands\tablecmds.cpp

cpp 复制代码
/*
 * es_get_starelkind
 *     获取通用的starelkind
 *
 * @return:
 *     返回通用的starelkind
 */
char es_get_starelkind()
{
    return STARELKIND_CLASS; // 返回表示类的starelkind
}

/*
 * es_get_stainherit
 *     获取通用的stainherit
 *
 * @return:
 *     返回通用的stainherit
 */
bool es_get_stainherit()
{
    return false; // 返回false,表示不继承
}

es_build_vacattrstats_array 函数

函数 es_build_vacattrstats_array 用于为数据库表添加或删除统计信息构建 VacAttrStats 数组。其主要功能包括:

  1. 获取关系信息: 获取表的 OID类型
  2. 遍历多列 Bitmapset 列表: 遍历给定的多列 Bitmapset 列表,检查每个多列统计信息是否已存在
  3. 构建新的统计信息结构: 对于需要添加的统计信息 ,调用 examine_attribute 函数构建 VacAttrStats 结构,并将其标记为有效。
  4. 填充 VacAttrStats 数组: 将构建的 VacAttrStats 结构填充到数组中,并更新数组长度
  5. 发出警告信息: 如果某些统计信息已存在或未定义,根据操作类型(添加或删除)发出相应的警告。
  6. 释放资源: 释放用于存储中间结果的列表资源

通过这些步骤,es_build_vacattrstats_array 函数确保在为表添加或删除统计信息时,能够正确构建和管理 VacAttrStats 结构,为后续的统计信息更新提供必要的数据支持。详细代码描述如下所示:(路径:src\common\backend\utils\adt\extended_statistics.cpp

cpp 复制代码
/*
 * es_build_vacattrstats_array
 *     为添加或删除统计信息构建VacAttrStats
 *
 * @param (in) rel:
 *     关系(表)
 * @param (in) bmslist_multicolumn:
 *     多列attnums的Bitmapset列表
 * @param (in) add_or_delete:
 *     标记添加或删除统计信息的标志
 *     true: 添加
 *     false: 删除
 * @param (out) array_length:
 *     结果数组的大小
 * @param (in) inh:
 *     是否继承
 *
 * @return:
 *     VacAttrStats的数组
 */
VacAttrStats** es_build_vacattrstats_array(
    Relation rel, List* bmslist_multicolumn, bool add_or_delete, int* array_length, bool inh)
{
    Oid relid = rel->rd_id; // 获取关系的OID
    char relkind = es_get_starelkind(); // 获取关系类型

    /* VacAttrStats列表 */
    List* vacattrstats_list = NIL; // 初始化VacAttrStats列表

    bool flagExistsEvent = false; // 标记是否存在已定义的事件

    ListCell* lc = NULL; // 列表单元指针
    foreach (lc, bmslist_multicolumn) {
        Bitmapset* bms_multi_column = (Bitmapset*)lfirst(lc); // 获取当前多列Bitmapset

        /* 搜索这个扩展统计信息,如果已定义则跳过 */
        bool exists = es_is_multicolumn_stats_exists(relid, relkind, inh, bms_multi_column);
        if ((add_or_delete && exists) || ((!add_or_delete) && (!exists))) {
            flagExistsEvent = true;
            continue;
        }

        /* 构建新的统计信息结构 */
        VacAttrStats* vacAttrStats = examine_attribute(rel, bms_multi_column, true);
        if (NULL == vacAttrStats) {
            continue;
        }
        vacAttrStats->anl_context = CurrentMemoryContext; // 设置分析上下文
        vacAttrStats->stats_valid = true; // 标记统计信息有效

        /* 插入到统计信息列表 */
        vacattrstats_list = lappend(vacattrstats_list, vacAttrStats);
    }

    *array_length = 0; // 初始化数组长度
    VacAttrStats** vacattrstats_array = NULL; // 初始化VacAttrStats数组
    if (NIL != vacattrstats_list) {
        *array_length = list_length(vacattrstats_list); // 获取列表长度
        vacattrstats_array = (VacAttrStats**)palloc0(list_length(vacattrstats_list) * sizeof(VacAttrStats*)); // 分配内存
        int i = 0; // 数组索引
        ListCell* lc_stats = NULL; // 统计信息列表单元指针
        foreach (lc_stats, vacattrstats_list) {
            vacattrstats_array[i] = (VacAttrStats*)lfirst(lc_stats); // 填充数组
            ++i;
        }
    }

    // 如果多列统计信息列表的长度与数组长度不一致且存在已定义的事件,则发出警告
    if (list_length((List*)bmslist_multicolumn) != *array_length && flagExistsEvent) {
        if (add_or_delete) {
            elog(WARNING, "Some of extended statistics have already been defined.");
        } else {
            elog(WARNING, "Some of extended statistics have not been defined.");
        }
    }

    list_free(vacattrstats_list); // 释放VacAttrStats列表

    return vacattrstats_array; // 返回VacAttrStats数组
}
相关推荐
yuenblue22 分钟前
什么是ondelete cascade以及使用sqlite演示ondelete cascade使用案例
数据库·sqlite
howard_shooter25 分钟前
Oracle Managed Files(OMF)
数据库·oracle
yangfeipancc1 小时前
数据库-用户管理
android·数据库
fen_fen2 小时前
mysql,mariadb,postgresql创建用户和授权的命令
mysql·postgresql·mariadb
两点王爷3 小时前
Java读取csv文件内容,保存到sqlite数据库中
java·数据库·sqlite·csv
凡人的AI工具箱4 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
2401_871213304 小时前
mysql之MHA
数据库·mysql
言之。5 小时前
【MySQL】事务
数据库·mysql
潇湘秦5 小时前
Oracle 11G还有新BUG?ORACLE 表空间迷案!
数据库·oracle
凡人的AI工具箱5 小时前
每天40分玩转Django:Django Email
数据库·人工智能·后端·python·django·sqlite