
一、参数配置
opengauss=# select * from pg_settings where name like '%delta%';-[ RECORD 1 ]-------------------------------name | enable_delta_storesetting | onunit |category | Query Tuningshort_desc | Enable delta for column store.extra_desc |context | postmastervartype | boolsource | configuration filemin_val |max_val |enumvals |boot_val | offreset_val | onsourcefile | opt/mogdb/data/postgresql.confsourceline | 803
二、创建测试表
opengauss=# create table test_cstore(id int,name varchar(20),insert_time timestamptz not null default now()) with (orientation=column,deltarow_threshold=1000);CREATE TABLEopengauss=# create table test_astore(id int,name varchar(20),insert_time timestamptz not null default now()) with (orientation=row);CREATE TABLE

opengauss=# select oid,relname from pg_class where relname like '%test_%';oid | relname-------+-------------25150 | test_cstore25315 | test_astore(2 rows)

opengauss=#select pg_relation_filepath('test_cstore');pg_relation_filepath----------------------base/25149/25150(1 row)opengauss=# select pg_relation_filepath('cstore.pg_cudesc_25150');pg_relation_filepath----------------------base/25149/25157(1 row)opengauss=# select pg_relation_filepath('cstore.pg_delta_25150');pg_relation_filepath----------------------base/25149/25154(1 row)omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ ll base/25149/25150*-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25150-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25150_C1.0-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25150_C2.0-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25150_C3.0omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ ll base/25149/25157*-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25157omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ ll base/25149/25154*-rw------- 1 omm dbgrp 0 Dec 7 21:45 base/25149/25154
pg_relation_filepath----------------------base/25149/25315(1 row)opengauss=# \qomm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ ll base/25149/25178*-rw------- 1 omm dbgrp 0 Dec 7 21:46 base/25149/25315
三、插入数据测试
3.1 插入单条数据
列存表
opengauss=# insert into test_cstore values(1,'test1');INSERT 0 1opengauss=# select * from test_cstore;id | name | insert_time----+-------+-------------------------------1 | test1 | 2023-12-07 22:17:53.571677+08(1 row)opengauss=# select * from cstore.pg_cudesc_25150;col_id | cu_id | min | max | row_count | cu_mode | size | cu_pointer | magic | extra--------+-------+-----+-----+-----------+---------+------+------------+-------+-------(0 rows)opengauss=# select * from cstore.pg_delta_25150;id | name | insert_time----+-------+-------------------------------1 | test1 | 2023-12-07 22:17:53.571677+08(1 row)
#原始列存表omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/25150*0 base/25149/251500 base/25149/25150_C1.00 base/25149/25150_C2.00 base/25149/25150_C3.0#pg_cudesc表omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/25157*0 base/25149/25157#pg_delta表omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/25154*8.0K base/25149/25154
opengauss=# select * from test_cstore;id | name | insert_time----+-------+-------------------------------1 | test1 | 2023-12-07 22:17:53.571677+08(1 row)opengauss=# select * from cstore.pg_delta_25150;id | name | insert_time----+-------+-------------------------------1 | test1 | 2023-12-07 22:17:53.571677+08(1 row)opengauss=# select pg_relation_filepath('cstore.pg_delta_25150');pg_relation_filepath----------------------base/25149/25154(1 row)
omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ hexdump -C base/25149/2518400000000 00 00 00 00 e0 4d 22 1e c6 ca 40 00 2c 00 d0 1f |.....M"...@.,...|00000010 00 20 06 20 00 00 00 00 67 3a 00 00 00 00 00 00 |. . ....g:......|00000020 00 00 00 00 00 00 00 00 d0 9f 60 00 00 00 00 00 |..........`.....|00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*00001fd0 03 00 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |................|00001fe0 01 00 03 00 02 0b 18 00 01 00 00 00 0d 74 65 73 |.............tes|00001ff0 74 31 00 00 00 00 00 00 5d 3f f1 e6 ea ae 02 00 |t1......]?......|00002000

16进制的01对应的10进制的1
16进制的74对应的10进制的116,ascii 码对应为t
16进制的65对应的10进制的101,ascii 码对应为e
16进制的73对应的10进制的115,ascii 码对应为s
16进制的74对应的10进制的115,ascii 码对应为t
16进制的31对应的10进制的49,ascii 码对应为1
行存表
opengauss=# insert into test_astore select * from test_cstore ;INSERT 0 1opengauss=# select * from test_astore;id | name | insert_time----+-------+-------------------------------1 | test1 | 2023-12-07 22:17:53.571677+08(1 row)opengauss=# select pg_relation_filepath('test_astore');pg_relation_filepath----------------------base/25149/25315(1 row)opengauss=# \qomm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/25315*8.0K base/25149/25315omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/25315*8.0K base/25149/25315omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ hexdump -C base/25149/2531500000000 00 00 00 00 28 ed 2e 1e 18 eb 40 00 2c 00 d0 1f |....(.....@.,...|00000010 00 20 06 20 00 00 00 00 7d 3a 00 00 00 00 00 00 |. . ....}:......|00000020 00 00 00 00 00 00 00 00 d0 9f 60 00 00 00 00 00 |..........`.....|00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*00001fd0 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|00001fe0 01 00 03 00 02 09 18 00 01 00 00 00 0d 74 65 73 |.............tes|00001ff0 74 31 00 00 00 00 00 00 5d 3f f1 e6 ea ae 02 00 |t1......]?......|00002000
测试结果
经过测试,列存表test_cstore的deltarow_threshold指定为1000,压缩级别为默认的low。后当插入单条数据,数据条数未达到deltarow_threshold指定值的情况下,系统上查看物理文件,可以看出数据仅存储到了pg_delta表中。 原始列存表中没有数据。数据库中读取的表的数据来自于pg_delta表。相当于在数据库层面做了一个映射。pg_delta表和原列存表的数据均取自pg_delta对应的物理文件。 产生的pg_delta表的数据存储方式是行存,它的结构以及物理文件存储形式和单纯以行存表保存的数据完全一致。同样数据的情况下,列存的pg_delta表和普通行存表数据文件对比如下,数据块的排布也是完全一致:

其他现象分析
omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ ll base/25149/25181-rw------- 1 omm dbgrp 0 Dec 8 00:21 base/25149/25181omm@ubuntu-linux-22-04-desktop:/opt/mogdb/data$ du -sh base/25149/251810 base/25149/25181

opengauss=# select pg_relation_filepath('test_cstore');pg_relation_filepath----------------------base/25149/25181(1 row)opengauss=# select oid,relfilenode from pg_class where relfilenode='25181';oid | relfilenode-------+-------------25150 | 25181(1 row)opengauss=# \dt cstore.*25150*List of relationsSchema | Name | Type | Owner | Storage--------+-----------------+-------+-------+-----------------------cstore | pg_cudesc_25150 | table | omm | {internal_mask=33031}cstore | pg_delta_25150 | table | omm | {internal_mask=32768}(2 rows)

3.2 继续插入999条数据
列存表
insert into test_cstore select generate_series(1,999),left(md5(random()::text),10);

可以发现1000条数据,达到了deltarow_threshold阈值的情况下,数据依然在数据库里原始表和pg_delta表里能查到条数。
而去系统上看物理文件,可以看到1000条数据依旧存在pg_delta表中。

行存表
依旧和列存插入一样的数据。

测试结果
3.3 继续插入1条单条数据
比赛安排
insert into test_cstore values(1001,'test1001');select count(*) from test_cstore;select count(*) from cstore.pg_cudesc_25150;select count(*) from cstore.pg_delta_25150;



行存表
行存表预期正常,此处无需做对比。

比赛安排
手动做vacuum deltamerge操作
手动对原始列存表做一次vacuum merge操作之后,发现pg_delta表里的数据已经清空了,而pg_cudesc表里有了四条记录,但是原始列存表的条数是不变的,此外原始列存表对应的物理文件也是自始至终不会存储数据的,数据只存在pg_detla表或者cu对应的列存表里。

这个时候查询:

更换relfilenode,使用新的物理文件的原因猜想可能是为了并发操作,尽可能减少行列转换过程,pg_delta表对更新或者插入的影响。可以一边用旧的文件进行行转列,一边用新的物理文件继续追加新的数据到pg_delta表里,vacuum DELTAMERGE过程申请AccessExclusiveLock。



其中,生成的C2文件内容如下,转成规范十六进制+ASCII显示便于观察,这一个文件预期应该存储第二列name列的数据:

查找到之前插入的test1001。可以看到它相邻的都是这一列上对应的数据。列上的数据是堆积在一起的:


3.4 单点查询,数据分别在pg_delta和cu里区别
870f6110e6的数据在cu里,test1002的数据在pg_delta表里,可以看到,没有索引,仅做单点查询的情况下,无论数据是在cu表里还是在pg_delta里,执行计划是一样的,都显示cstore scan 访问原始列存表。

数据库重启不会影响数据在cu文件和pg_delta里的分布,也不会进行行列转换。

3.5 行转列的最大记录数限制测试(MAX_BATCHROW)
列存表一次性插入60000条数据


列存表一次性插入61000条数据


测试结果
一次性插入数条数在进行行转列的时候,有最大值限制,60000是最大值,超出的会拆分成另一个cu_id,然后把记录写入到pg_cudesc里。 这次因为单次的插入值大于deltarow_threshold,直接触发了行转列,而不需要手动vacuum deltamerge操作。deltarow_threshol是指定列存表导入时小于多少行的数据进入delta表,而并不是一个delta中数据累积触发的,是单次插入的行数阈值。跟单次写入的行数有关。
关于作者
END
访问官网了解更多:www.mogdb.io
产品兼容适配申请:partner@enmotech.com
加微信进入交流群:Roger_database






