首页 > 其他分享 >openGauss的索引组织表

openGauss的索引组织表

时间:2024-03-18 16:14:05浏览次数:21  
标签:2200 10 组织 聚簇 索引 relfilenode test openGauss

openGauss 的索引组织表

概述

今天有位小伙伴问我,Oracle 数据库可以通过索引组织表(IOT)将数据按照主键排序存储,有序的数据存储可以有效提高数据库缓冲区的命中率,减少 SQL 查询的 IO 消耗,提升查询效率。而 openGauss 的建表语句中并没有看到索引组织表的相关语法。openGauss 目前是不是不支持索引组织表?

我觉得暂时是这样的(说不定后期版本会新添加),在 openGauss 的官方文档中有关建表操作中确实没有看到对索引组织表的描述,但是与索引组织表效果类似的操作确是可以看到,那就是 cluster 操作,个人认为这个功能与索引组织表的主要功能类似:数据按照索引顺序进行有序存储。

使用 cluster 操作可以根据表的索引对数据进行聚簇排序,将数据基于索引信息进行物理存储。但在 openGauss 中,这种聚簇排序操作是一次性的,即:当表被更新之后, 更改的内容不会自动被聚簇排序后存储。也就是说,系统不会试图按照索引顺序对新的存储内容及更新记录进行重新聚簇排序存储。

当一个表聚簇(CLUSTER 操作)之后,openGauss 会记录在哪个索引上建立了聚簇。用户可以通过CLUSTER操作在之前的同一个索引的表上重新聚簇排序,也可以用ALTER TABLE CLUSTERSET WITHOUT CLUSTER形式来设置索引来用于后续的聚簇操作或清除任何之前的设置。

表的聚簇操作(CLUSTER)大致分为以下几步:

  1. 检查堆表和索引是否满足聚簇要求;
  2. 获取目标表和索引的排它锁(exclusive lock);
  3. 标记指定的索引为聚簇依据;
  4. 根据目标表的数据和索引,拷贝数据并创建一个有序存储的临时表;
  5. 交换临时表和目标表的 relfilenode,以确保目标表的 OID 不会发生变化(数据库根据 OID 管理对象);
  6. 调用 reindex 重建目标表的索引;
  7. 反馈 vacuum full 状态给统计线程;
  8. 清除表的 CLUSTER 操作状态。

语法格式

  • 对一个表进行聚簇排序

    CLUSTER [ VERBOSE ] table_name [ USING index_name ];
    
  • 对一个分区进行聚簇排序

    CLUSTER [ VERBOSE ] table_name PARTITION ( partition_name ) [ USING index_name ];
    
  • 对已做过聚簇的表重新进行聚簇

    CLUSTER [ VERBOSE ];
    

说明:

不含参数的 CLUSTER 会将当前用户所拥有的数据库中的先前做过聚簇的所有表重新处理。

测试示例

创建测试表和索引

postgres=> create tablespace tbs1 relative location 'tablespace/tbs1' ;
CREATE TABLESPACE
postgres=> create table test tablespace tbs1
	   as
	   select relname,relnamespace,relowner,relfilenode from pg_class;
INSERT 0 648
postgres=> create index test_idx on test(relfilenode) tablespace tbs1;
CREATE INDEX

查询表信息

postgres=> \d test
       Table "public.test"
    Column    | Type | Modifiers
--------------+------+-----------
 relname      | name |
 relnamespace | oid  |
 relowner     | oid  |
 relfilenode  | oid  |
Indexes:
    "test_idx" btree (relfilenode) TABLESPACE tbs1, tablespace "tbs1"
Tablespace: "tbs1"

postgres=> select oid,relname,relpages,reltablespace,relfilenode
	   from pg_class
	   where relname like '%test%';
  oid  | relname  | relpages | reltablespace | relfilenode
-------+----------+----------+---------------+-------------
 17187 | test     |        9 |         16385 |       17187
 17190 | test_idx |        4 |         16385 |       17190


postgres=> select ctid,* from test
	   order by relfilenode desc
	   limit 10;
  ctid  |       relname        | relnamespace | relowner | relfilenode
--------+----------------------+--------------+----------+-------------
 (2,8)  | test                 |         2200 |       10 |       17187
 (1,40) | emp1_empno_idx       |         2200 |       10 |       17169
 (1,12) | emp1                 |         2200 |       10 |       17166
 (0,30) | t3                   |         2200 |       10 |       17154
 (0,29) | t2                   |         2200 |       10 |       17150
 (0,28) | t2_id_seq            |         2200 |       10 |       17148
 (0,27) | seq01                |         2200 |       10 |       17147
 (0,26) | seq02                |         2200 |       10 |       17145
 (0,25) | pg_toast_17129_index |           99 |       10 |       17142
 (0,24) | pg_toast_17129       |           99 |       10 |       17140

备注:ctid表示数据记录的物理行位置信息,格式为(blockid,offset)

通过以上操作我们可以获得以下信息:

  1. 当前创建的测试表和索引存储在同一个表空间(16385);
  2. 表 test 的 oid 为 17178 且数据文件名为 17178;
  3. 索引 test_idx 的 oid 为 17190 且数据文件名为 17190;
  4. 表 test 的数据存储物理位置并没有按照索引进行排序(ctid),查询操作至少需要读取 3 个数据块的数据(默认堆表是无序存储)。

执行 cluster 操作

postgres=> cluster test using test_idx ; CLUSTER

查询表信息

postgres=> \d test
       Table "public.test"
    Column    | Type | Modifiers
--------------+------+-----------
 relname      | name |
 relnamespace | oid  |
 relowner     | oid  |
 relfilenode  | oid  |
Indexes:
    "test_idx" btree (relfilenode) TABLESPACE tbs1 CLUSTER, tablespace "tbs1"
Tablespace: "tbs1"

postgres=> select oid,relname,relpages,reltablespace,relfilenode from pg_class where relname like '%test%';
  oid  | relname  | relpages | reltablespace | relfilenode
-------+----------+----------+---------------+-------------
 17187 | test     |        9 |         16385 |       17191
 17190 | test_idx |        4 |         16385 |       17194

postgres=> insert into test select relname,relnamespace,relowner,relfilenode from pg_class where relfilenode in (17154,17169);
INSERT 0 2

postgres=> select ctid,* from test order by relfilenode desc limit 10;
  ctid  |    relname     | relnamespace | relowner | relfilenode
--------+----------------+--------------+----------+-------------
 (8,48) | test           |         2200 |       10 |       17187
 (8,47) | emp1_empno_idx |         2200 |       10 |       17169
 (8,50) | emp1_empno_idx |         2200 |       10 |       17169
 (8,46) | emp1           |         2200 |       10 |       17166
 (8,45) | t3             |         2200 |       10 |       17154
 (8,49) | t3             |         2200 |       10 |       17154
 (8,44) | t2             |         2200 |       10 |       17150
 (8,43) | t2_id_seq      |         2200 |       10 |       17148
 (8,42) | seq01          |         2200 |       10 |       17147
 (8,41) | seq02          |         2200 |       10 |       17145

通过对表进行 cluster 操作,我们可以看到以下变化:

  1. test 的索引 test_idx 已经被标记为 CLUSTER,openGauss 已经记录在哪个索引上建立了聚簇;
  2. 索引 test_idx、表 test 的 OID 和对应的表空间并没有发生变化,但是 relfilenode 却发生了变化,这说明在 cluster 操作过程中,数据文件本身已经发生了变化,不再是原先的那个数据文件。
  3. 最明显的是表中的数据已经按照索引列 relfilenode 进行排序,查询的这 10 行数据都在同一个数据块(blockid=8)中存储,只需要读取一个数据块就可以获得目标数据。
  4. 后插入的数据(relfilenode=17169 和 17154)并不会按照 test_idx 索引进行聚簇排序存储。

小结

通过对表的 cluster 操作,可以将堆表内的数据进行有序存储(类似于 oracle 的索引组织表功能),在一定程度上可以降低 SQL 查询的 IO 消耗,但是让人头疼的是每次 cluster 操作时带来的表锁问题(测试数据未显示)使得该操作只能在业务空闲期由 DBA 手动执行,而且 cluster 操作所需的时间和空间的估算需要依据目标表和索引的具体量级和硬件环境而定。 另外,当数据进行有序存储后,表的统计信息可能与实际的情况差异较大,为了避免 CBO 优化器的误判,建议对目标表手动发起一次 ANALYZE。

在官方文档中还指出:cluster 操作不支持在事务中执行,且仅支持行存引擎的 Btree 索引,这两点也是需要注意的限制条件。

TIPS

关于数据有序存储,在列存引擎中可以使用 Psort 索引进行数据批量导入时的局部排序,减少 CU 之间的数据交集和误读现象,大幅降低 SQL 查询对磁盘 IO 的消耗。

关于 MOT 这个内存引擎,磁盘的 IO 应该不算是瓶颈问题,有序存储显得也不那么重要了,可以忽略。MOT 更应该考虑的是并发访问的锁瓶颈和 CPU、内存交互带来的延迟等问题。

标签:2200,10,组织,聚簇,索引,relfilenode,test,openGauss
From: https://www.cnblogs.com/renxyz/p/18080626

相关文章

  • step-by-step系列之-openGauss1-0-1-Docker版本单机安装指南
    stepbystep系列之:openGauss1.0.1Docker版本单机安装指南1.软硬件环境硬件环境:项目最低配置推荐配置测试配置硬盘用于安装openGauss的硬盘需最少满足如下要求:至少1GB用于安装openGauss的应用程序包。每个主机需大约300MB用于元数据存储。预留70%以上的磁盘剩......
  • step-by-step之-install-docker版本opengauss1-0-1主备机群
    stepbystep之:installdocker版本opengauss1.0.1主备机群实验环境说明:OS:2颗8核心8GB内存。1.流程:先安装docker软件,下载Docker镜像,在创建启动主备容器数据库,进入数据库,进行主备切换试验。2.安装docker软件[root@node1~]#yum-yinstalldocker#检查docke......
  • openGauss增量备份恢复
    openGauss增量备份恢复openGauss数据库自2020年6月30日发布以来,很多小伙伴都提到“openGauss数据库是否有增量备份工具?“这么一个问题。在openGauss1.0.0版本的时候,关于这个问题的回答往往是:“Sorry…”,openGauss数据库可以使用gs_basebackup工具对数据库进行物......
  • openGauss的WDR报告详细解读
    openGauss的WDR报告详细解读openGauss数据库自2020年6月30日开源至今已有10个月了,在这短短的10个月内,openGauss社区用户下载量已达13W+、issue合并2000+、发行商业版本6个。仅3月份就有11家企业完成CLA签署,包括虚谷伟业、云和恩墨、优炫软件、海量数据......
  • openGauss数据动态脱敏
    openGauss数据动态脱敏常见脱敏路线结果集解析:不改写发给数据库的语句,需要提前获悉数据表结构,待数据库返回结果后再根据表结构判断集合内哪些数据需要脱敏,并逐条改写结果数据。语句改写:将包含敏感字段查询的语句改写,对于查询中涉及的敏感字段(表列)通过外层嵌套函数的方式改写......
  • 浅聊openGauss体系架构
    浅聊openGauss体系架构2020年7月openGauss刚刚开源,我便开始对openGauss数据库的学习。根据以往学习数据库的经验,最先想了解的是openGauss数据库的架构,希望对即将使用的数据库各个模块有所了解。但鉴于时间有限,仅有的资料图是源码doc目录内的“openGauss逻辑结构图......
  • 浅聊openGauss逻辑架构
    浅聊openGauss逻辑架构概述openGauss数据库是一款由华为主导、各个生态合作伙伴共同建设的开源关系型数据库管理系统,开源发行协议遵从木兰宽松许可证v2。openGauss数据库源于PostgreSQL-XC项目,内核源于Postgres9.2.4,总代码量约120W行,其中内核代码约95W行。华为结......
  • SQL 查询优化之 WHERE 和 LIMIT 使用索引详解
    奇怪的慢sql我们先来看2条sql第一条:第二条:表的索引及数据总情况: 索引:acct_id,create_time分别是单列索引,数据库总数据为500w。通过acct_id过滤出来的结果集在1w条左右。 查询结果:第一条要5.018s,第二条0.016s为什么会是这样的结果呢?第一,acct_id和create_time都有索引,不......
  • Mybatis-plus构建wrapper条件时出现索引越界异常Caused by: org.apache.ibatis.except
    项目场景:学习springboot整合mybatis-plus时通过构建器执行相关操作@AutowiredBookMappermapper;@Testvoidtest(){QueryWrapper<Book>wrapper=newQueryWrapper<>();wrapper.select("id","name","press")//只查询前三......
  • MySQL--索引
    目录一.MySQL的索引能提高效率的原因主要有以下几点:二.索引的类型三.EXPLAIN执行计划分析四.什么情况添加索引五.联合索引注意哪些细节六.不合理使用索引的场景七.MySQL为什么有时会选错索引一.MySQL的索引能提高效率的原因主要有以下几点:快速定位数据:索引是一种数......