首页 > 其他分享 >openGauss 列存表PSort索引

openGauss 列存表PSort索引

时间:2024-04-10 11:57:43浏览次数:24  
标签:indice bufferedBatchRows Assert PSort 索引 relation openGauss 列存表

openGauss 列存表 PSort 索引
概述
PSort(Partial sort) Index 是在列存表的列上建的聚簇索引。CUDesc 上有每个 CU 的 min 和 max 值,但如果业务的数据模型较为离散,查询时通过 min 和 max 值去过滤 CU 会出现大量的 CU 误读取,例如每个 CU 的 min 和 max 跨度都比较大时,其查询效率接近全表扫描。例如下图中的场景,查询 2 基本命中所有的 CU, 此时查找近似全表扫描。

PSort 索引可以对部分区间(一般会包含多个 CU 覆盖的行)内的数据按照索引键进行排序,使得 CU 之间的交集尽量减少,提升查询的效率。

PSort 索引使用
在批量插入列存表的过程中,如果发现有 PSort 索引,会先对这批数据进行排序。PSort 索引表的组织形式也是 cstore 表(CUDesc 是 astore 表),表的字段包含了索引键的各个字段,加上对应的行号(TID)字段。插入数据的过程中如果发现有 PSort 索引,会将一定数量的数据按照 PSort 索引的索引键进行排序,与 TID 字段共同拼装成向量数组,再插入到 PSort 索引的 cstore 表中。 所以 PSort 索引数据中列数比实际的索引键要多一列,多出的这一列用于存储这条记录在数据 cstore 存储中的位置。

// 构建 PSort 索引过程中构造索引数据
inline void ProjectToIndexVector(VectorBatch *scanBatch, VectorBatch *outBatch, IndexInfo *indexInfo)
{
Assert(scanBatch && outBatch && indexInfo);
int numAttrs = indexInfo->ii_NumIndexAttrs;
AttrNumber *attrNumbers = indexInfo->ii_KeyAttrNumbers;
Assert(outBatch->m_cols == (numAttrs + 1));

// index column
for (int i = 0; i < numAttrs; i++) {
    AttrNumber attno = attrNumbers[i];
    Assert(attno > 0 && attno <= scanBatch->m_cols);

    // shallow copy
    outBatch->m_arr[i].copy(&scanBatch->m_arr[attno - 1]);
}

// ctid column
// 最后一列是 tid
outBatch->m_arr[numAttrs].copy(scanBatch->GetSysVector(-1));

outBatch->m_rows = scanBatch->m_rows;

}
cstore 表执行插入流程,如果有 Psort 索引,会先将数据插入排序队列

void CStoreInsert::BatchInsert(in VectorBatch* pBatch, in int options)
{
Assert(pBatch || IsEnd());

/* keep memory space from leaking during bulk-insert */
MemoryContext oldCnxt = MemoryContextSwitchTo(m_tmpMemCnxt);

// Step 1: relation has partial cluster key
// We need put data into sorter contatiner, and then do
// batchinsert data
if (NeedPartialSort()) {
    Assert(m_tmpBatchRows);

    if (pBatch) {
        Assert(pBatch->m_cols == m_relation->rd_att->natts);
        m_sorter->PutVecBatch(m_relation, pBatch); // 插入局部排序队列
    }

    if (m_sorter->IsFull() || IsEnd()) { // 排序队列满了或者插入数据输入结束
        m_sorter->RunSort(); // 按照索引键排序

        /* reset and fetch next batch of values */
        DoBatchInsert(options);
        m_sorter->Reset(IsEnd());

        /* reset and free all memory blocks */
        m_tmpBatchRows->reset(false);
    }
}

// Step 2: relation doesn't have partial cluster key
// We need cache data until batchrows is full
else {
    Assert(m_bufferedBatchRows);

    // If batch row is full, we can do batchinsert now
    if (IsEnd()) {
        if (ENABLE_DELTA(m_bufferedBatchRows)) {
            InsertDeltaTable(m_bufferedBatchRows, options);
        } else {
            BatchInsertCommon(m_bufferedBatchRows, options);
        }
        m_bufferedBatchRows->reset(true);
    }

    // we need cache data until batchrows is full
    if (pBatch) {
        Assert(pBatch->m_rows <= BatchMaxSize);
        Assert(pBatch->m_cols && m_relation->rd_att->natts);
        Assert(m_bufferedBatchRows->m_rows_maxnum > 0);
        Assert(m_bufferedBatchRows->m_rows_maxnum % BatchMaxSize == 0);

        int startIdx = 0;
        while (m_bufferedBatchRows->append_one_vector(
                   RelationGetDescr(m_relation), pBatch, &startIdx, m_cstorInsertMem)) {
            BatchInsertCommon(m_bufferedBatchRows, options);
            m_bufferedBatchRows->reset(true);
        }
        Assert(startIdx == pBatch->m_rows);
    }
}

// Step 3: We must update index data for this batch data
// if end of batchInsert
FlushIndexDataIfNeed();

MemoryContextReset(m_tmpMemCnxt);
(void)MemoryContextSwitchTo(oldCnxt);

}

图 cstore 表插入流程示意图

插入流程中更新索引数据的代码

void CStoreInsert::InsertIdxTableIfNeed(bulkload_rows* batchRowPtr, uint32 cuId)
{
Assert(batchRowPtr);

if (relation_has_indexes(m_resultRelInfo)) {
    /* form all tids */
    bulkload_indexbatch_set_tids(m_idxBatchRow, cuId, batchRowPtr->m_rows_curnum);

    for (int indice = 0; indice < m_resultRelInfo->ri_NumIndices; ++indice) {
        /* form index-keys data for index relation */
        for (int key = 0; key < m_idxKeyNum[indice]; ++key) {
            bulkload_indexbatch_copy(m_idxBatchRow, key, batchRowPtr, m_idxKeyAttr[indice][key]);
        }

        /* form tid-keys data for index relation */
        bulkload_indexbatch_copy_tids(m_idxBatchRow, m_idxKeyNum[indice]);

        /* update the actual number of used attributes */
        m_idxBatchRow->m_attr_num = m_idxKeyNum[indice] + 1;

        if (m_idxInsert[indice] != NULL) {
            /* 插入PSort 索引 */
            m_idxInsert[indice]->BatchInsert(m_idxBatchRow, 0);
        } else {
            /* 插入 cbtree/cgin 索引 */
            CStoreInsert::InsertNotPsortIdx(indice);
        }
    }
}

}
索引插入流程和普通 cstore 数据插入相同。

使用 PSort 索引查询时,由于 PSort 索引 CU 内部已经有序,因此可以使用二分查找快速找到对应数据在 psort 索引中的行号,这一行数据的 tid 字段就是这条数据在数据 cstore 中的行号。

图-2 PSort 索引查询示意图

标签:indice,bufferedBatchRows,Assert,PSort,索引,relation,openGauss,列存表
From: https://www.cnblogs.com/helloopenGauss/p/18125721

相关文章

  • openGauss数据与PostgreSQL的差异对比
    openGauss数据与PostgreSQL的差异对比前言openGauss数据库已经发布2.0.1版本了,中启乘数科技是一家专业的专注于极致性能的数据库服务提供商,所以也关注openGauss数据库的特性。因为openGauss是从PostgreSQL发展出来的,所以我们详细讲解对比一下openGauss与原生Po......
  • 一键部署openGauss2.0.1 CentOS 7.6
    一键部署openGauss2.0.1[CentOS7.6]本文档目的是为了帮助高校学生提供基于CentOS7.6操作系统,实现openGauss数据库一键式安装的脚本。该脚本执行成功后,所有关于openGauss数据库的文件将保存在/gaussdb目录中。脚本内容中“...”请替换为服务器实际的私有IP地址。脚......
  • openGauss 2.1.0 闪回特性
    openGauss2.1.0闪回特性openGauss2.1.0于2021年9月30日发布,是openGauss的一个Preview版本,该版本生命周期仅为半年。该版本的新增功能如下:存储过程兼容性增强SQL引擎能力增强支持Ustore存储引擎支持段页式存储基于Paxos分布式一致性协议的高可用AI4DB和......
  • openGauss数据库xlog目录满问题处理
    openGauss数据库xlog目录满问题处理openGauss数据库xlog满通常为以下几个原因:1.主备状态不正常,存在网络问题,集群内有宕机的节点2.xlog保留数量过多3.逻辑复制槽失效,且未及时清理4.开启归档,但归档失败导致xlog不清理首先,确认数据库状态gs_om-tquery确认主备状态......
  • HAProxy适配openGauss使用指导书
    一、HAProxy简介HAProxy是一个开源的项目,其代码托管在Github上,代码链接如下:HAProxy代码链接。HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy实现了一种事件驱动,单一进程模型,此模型支持非......
  • MogDB/openGauss 开机自启动
    MogDB/openGauss开机自启动在centos7.6操作系统上设置MogDB/openGauss开机自启动,我们先来了解一下自定义服务的配置文件组成部分,共分为[Unit]、[Service]、[Install]三个部分。[Unit]Description=当前服务的简单描述Documentation=服务配置文件的位置Before=在某服务......
  • 如何在openGauss 2.1.0中使用Job
    如何在openGauss2.1.0中使用Job如何在openGauss2.1.0中使用JobJob类似unix中的crontab,有定时执行的功能,可以在指定的时间点或每天的某个时间点等自行执行任务。在各类系统使用运行过程中,经常会遇到需要定时完成的任务,比如定时更新数据,定时统计数据生成报表等等,这些......
  • openGauss Gin 索引
    openGaussGin索引概述GIN(GeneralizedInvertedIndex)通用倒排索引,是首选的文本搜索索引类型。倒排索引对应的列上的数据类型通常是一个多值类型,索引中包含每个单词的索引条目,以及所匹配的位置的压缩列表。如果搜索条件是多个单词,可以先使用第一个单词进行匹配,再在找到的结果中......
  • openGauss2.1.0新特性-账本数据库实验
    openGauss2.1.0新特性-账本数据库实验账本数据库融合了区块链思想,将用户操作记录至两种历史表中:用户历史表和全局区块表。当用户创建防篡改用户表时,系统将自动为该表添加一个hash列来保存每行数据的hash摘要信息,同时在blockchain模式下会创建一张用户历史表来记录对应用户......
  • 如何在openGauss 2.1.0中使用Job
    如何在openGauss2.1.0中使用Job如何在openGauss2.1.0中使用JobJob类似unix中的crontab,有定时执行的功能,可以在指定的时间点或每天的某个时间点等自行执行任务。在各类系统使用运行过程中,经常会遇到需要定时完成的任务,比如定时更新数据,定时统计数据生成报表等等,这些......