【MogDB】MogDB5.2.0重磅发布第三篇-支持astore下的rowid

一、背景

从ORACLE迁移到国产数据库,经常会遇到rowid的兼容性问题,可能是不支持rowid这个关键字,也可能是rowid数据类型或rowid的行为和oracle不一样。

  • rowid特征:
  1. rowid是表上的一个伪列
  2. rowid字段在数据字典中不存在
  3. select * from tab时,不显示rowid字段
  4. select rowid from tab能查出rowid列
  5. rowid的值对于同一行比较稳定,但有些情况下可能会变
  6. 相同的一个rowid,在不同的时刻可能指向不同的行(比如删除记录再插入,可能会插入到之前的物理位置)
  • rowid常用场景:
  1. 使用rowid排序,确保无主键表的排序结果稳定性
  2. 删除表中的重复记录
  3. 使用rowid定位行,进行dml操作
  4. 把处理过的rowid记录存储下来,表示该行数据已经被处理过,无需对原表更新表示状态的字段(业务队列表)
  • oracle某行的rowid会变的几种情况:
  1. 对分区表的数据记录进行更新分区键字段的操作
  2. 手动执行move命令
  3. 手动执行shrink
  4. 压缩表
  5. 移动表空间

可以看到就算是正常进行dml操作,ORACLE的rowid也是可能会变化的,只是没那么容易变化。

但PG/OG系数据库中类似rowid的这种表示物理位置的字段叫ctid,每次更新这行记录后,都会发生"变化",但其实是"没变"的,更新是旧行标记作废,插入新行,新行的ctid和旧行不一样。

收集了一下目前知名的几家数据库是否支持ROWID

数据库基于PG/OG是否支持ROWID是否有提供改写方案
DMNY
崖山NY
OCEANBASENY
KINGBASEYY
POLARDB-OYY
TDSQLYY
UXDBYY
GAUSSDBYNY
OPENGAUSSYN同GAUSSDB
GBASE 8cYY
VASTBASE G100 BUILD 16YY
神通YY
海盒Y
瀚高Y??

对于从头开始纯自研的数据库来说,rowid的兼容自然不成问题,但基于PG或者源于PG的其他数据库来说,rowid的兼容并不简单,因为使用了astore这种存储引擎。很多家数据库声称支持了rowid,但是实际测试下来,有些场景和ORACLE的结果并不一致。

PG系如果要支持rowid,目前已知的大致有四种方案

  1. 借用ctid,但由于分区表的不同分区里可能出现相同的ctid,因此需要结合tableoid和ctid两个字段;如果是分布式的,还需要结合节点字段。但是记录被update时,ctid一定会变,不能使用同一个ctid去对某条记录进行两次更新。
  2. 在表上直接加一个物理存储的列,用于存储rowid,并且给它加上唯一约束或索引,而其值本身可能直接使用一个全局序列的值。
  3. 也是在表上直接加一个物理存储的列,但需要引入每个表的序列管理,这个序列值结合tableoid计算出一个base64编码的值,存到这个表里。
  4. 新增一种存储引擎,update数据时在原行上更新,不像astore这种更新实际上是插入了新行。

简单来说,PG系rowid实现其实也就两种,一种是再建一个字段存储唯一值,另一种就是ctid或其变种。前者带来大量性能损耗,后者一update就会变。

二、准备测试用例

1.select * 不显示rowid

create table test_rowid_update(id number,content varchar2(200));
insert into test_rowid_update values (1,'1');
select * from test_rowid_update ;
drop table test_rowid_update;

2.select rowid 不报错

create table test_rowid_update(id number,content varchar2(200));
insert into test_rowid_update values (1,'1');
select rowid,t.rowid,t.* from test_rowid_update t ;
drop table test_rowid_update;

3.通过rowid快速检索数据

create table test_rowid_update(id number,content varchar2(200));
insert into test_rowid_update select id,'id_'||id from generate_series(1,1000) id;
vacuum test_rowid_update;
vacuum test_rowid_update;
explain analyze select  t.* from test_rowid_update t where rowid = (select rowid from test_rowid_update  where content='id_50') ;
drop table test_rowid_update;

4.对同一个rowid进行多次更新

create table test_rowid_update(id number,content varchar2(200));
insert into test_rowid_update values (1,'1');declare
i int;
begin
for rec in (select rowid rd from test_rowid_update) loop
update test_rowid_update set content='2' where rowid=rec.rd;
update test_rowid_update set content='3' where rowid=rec.rd;
end loop;
select 1 into i from test_rowid_update where id=1 and content='3';
end;
/
select * from test_rowid_update where  id=1 and content='3';
drop table test_rowid_update ;

5.删除表中重复记录

create table test_rowid_update as select id,'n_'||id as content from generate_series(1,10) id;insert into test_rowid_update select id,'d_'||id from generate_series(1,5) id;DELETE FROM test_rowid_update t1
WHERE t1.rowid > (
SELECT MIN(t2.rowid)
FROM test_rowid_update t2
WHERE t1.id= t2.id
);

三、执行测试

1.DM 8

在线测试环境:https://eco.dameng.com/tour/
在这个环境中测试,得到DM的rowid是一个数字,可以认为它是一个自增主键。每个表的第一行记录的rowid是1,因此它表示一个逻辑位置,而非物理位置,在DM的一些官方文档中可以找到相关描述
https://eco.dameng.com/document/dm/zh-cn/pm/manage-table
https://eco.dameng.com/document/dm/zh-cn/pm/management-table
但是DM的下面这篇文档,却说是一个物理位置,而且演示的用例,rowid也不是数字了
https://eco.dameng.com/document/dm/zh-cn/pm/insertion-deletion-modification
出现这个差异的原因是,DM的表有索引组织表和堆表两种,默认建表是索引组织表,可以通过修改参数来修改默认行为

alter system set 'LIST_TABLE'=1 both;

在堆表情况下,rowid就不是从1开始的数字了,但它仍然是数字类型,该数字通过计算得到,没有进行实际存储

2.OCEANBASE 4.1

没有拿到免费的ORACLE租户环境,暂无法测试,但从文档来看

https://www.oceanbase.com/docs/common-oceanbase-database-cn-0000000001967397

OceanBase 数据库当前版本所支持的 ROWID 为逻辑 ROWID

https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001701107

ROWID 伪列提供了快速定位表中某一行的能力,ROWID 值由主键编码得到,不会进行实际的存储

http://www.oceanbase.wiki/concept/database-objects/oracle-mode/tables/oracle-mode-data-types/rowid-data-types/

ROWID 伪列的值是每行数据的 Key(对于有主键表是 Primary Key,对于无主键表是系统自动生成的序列),通过 Base64 编码转换而成

https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001699615

OceanBase 数据库的无主键表采用分区级自增列作为隐藏主键。

这意味着OceanBase并没有提供物理位置的rowid,而且对于非主键表,也会自动增加一个序列字段作为主键(分布式数据库的表必须要有主键?)。

3.崖山 23.1

环境准备:
https://download.yashandb.com/download
https://doc.yashandb.com/yashandb/23.1/zh/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2/%E5%AE%89%E8%A3%85%E5%89%8D%E5%87%86%E5%A4%87/%E5%AE%89%E8%A3%85%E5%89%8D%E5%87%86%E5%A4%87.html
https://doc.yashandb.com/yashandb/23.1/zh/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2/YashanDB%E4%BA%A7%E5%93%81%E5%AE%89%E8%A3%85/YashanDB%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%AE%89%E8%A3%85.html

yashandb的rowid格式像这个样子"2487:0:0:2532:0",准确指向物理位置,行被update后,rowid不会发生变化。但是注意直接粘贴匿名块到命令行客户端,会无法准确识别语句结束符,暂未找到相关文档说明。

4.KINGBASE 8

环境准备:

wget https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/05.Docker%E7%89%88%E6%9C%AC/kdb_x86_64_V009R001C001B0030.tar
docker load -i kdb_x86_64_V009R001C001B0030.tar
docker run -tid \
--privileged \
--name kingbase \
-p 54321:54321 \
-e ENABLE_CI=no  \
-e NEED_START=yes \
-e DB_USER=root \
-e DB_PASSWORD=root \
-e DB_MODE=oracle \
kingbase_v009r001c001b0030_single_x86:v1
docker exec -it kingbase /bin/bash
ksql -d test

在建表前需要先开启参数 set default_with_rowid to on; 表上才会有rowid字段,且该字段会是一个实际存在的字段,数据里会直接存储rowid的值,并且在这个字段上会自动创建一个主键约束。
虽然这种方式极大的保证了使用rowid处理数据的结果正确性,但它已经不是物理位置,而是逻辑位置,增加了额外的存储空间,并且会引发DML语句的性能问题,比如插入数据时,会去校验主键约束,数据插入完后,索引也要同步更新,然后vacuum时要同时处理表和索引;更新和删除记录时也是。

5.POLARDB-O

之前2.0版本免费公测的时候测了下,现在没有免费测试方法了,以下不代表最新版的情况。

众所周知,POLARDB-O 1.0来自于EDB,其实EDB处理rowid的方案和kingbase类似,也是要配置一个参数,参数名叫 default_with_rowids。不过kingbase的rowid是个字符串,而EDB的rowid是个bigint, 默认值是一个序列。
POLARDB-O 2.0版本中,无需配置参数(参数名改成了 polar_default_with_rowid),建表时直接就给你加了个 polar_sys_rowid_attr字段。稍微有点坑的是,这个字段在pg_attribute中记录的列号是大于0的,这意味着第三方工具(比如dbeaver)如果把它当成pg去查建表的ddl语句,则会出现表中多一列的情况,可惜当时没测再加列会是什么效果,希望有环境的伙伴可以验证一下再告诉我。

CREATE TABLE public.t1 (
a text NULL,
"polar_sys_rowid_attr" int8 NOT NULL DEFAULT nextval('polar_sys_seq'::regclass)
);CREATE INDEX polar_rowid_17309_index ON public.t1 USING btree("polar_sys_rowid_attr");

既然是新增了存储的信息,必然会导致性能受影响,在polardb官网文档中的性能测试相关描述中,特意说明了是在关闭了rowid这个功能后进行的测试
https://help.aliyun.com/zh/polardb/polardb-for-oracle/difference-between-2-0-and-1-0-versions-of-polardb-for-oracle

性能测试中的参数均保持一致,其中参数 polar_enable_stmt_transaction_rollbackpolar_default_with_rowid设置为 off,其余参数使用默认值。

6.openGauss和GaussDB

环境准备

vi og600.yamlglobal:  cluster_name: og600user: og600base_dir: /opt/og600rcdb_servers:- host: 127.0.0.1db_port: 21000
curl --proto '=https' --tlsv1.2 -sSf https://cdn-mogdb.enmotech.com/ptk/install.sh | sh
ptk checkos -o root_fix.sh
source root_fix.sh
ptk install -f og600.yaml -p https://opengauss.obs.cn-south-1.myhuaweicloud.com/6.0.0/openEuler20.03/x86/openGauss-All-6.0.0-openEuler20.03-x86_64.tar.gzsu - og600
gsql -r

不支持rowid,但是gaussdb的官方文档中,说明了应该要如何改写
https://support.huaweicloud.com/tg-dws/dws_mt_0128.html

select CAST((xc_node_id||'#'||tableoid||'#'||ctid ) AS TEXT ) AS rowid`

简单来说,gaussdb是分布式的,所以要拼一个xc_node_id,区分是哪个节点的数据;然后拼一个tableoid,因为不同的表中是会有相同的ctid的,为了保证唯一性,就拼了三个字段当成rowid去用。但是astore中,一旦该条记录被更新,ctid就会变,用这种方式拼出来的rowid也无法再找到刚刚被更新过的数据。
不过,在ustore引擎下,这个ctid就不会变化了,可以说openGauss/GaussDB从原理上可以支持不变的rowid,但是并没有支持 rowid这个关键字

7.VASTBASE G100 V2.2 BUILD 16

未提供公开的安装介质,找关系申请到了试用版本。
支持在查询中使用rowid伪列,不过情况和openGauss一样,虽然这个rowid长得和ORACLE类似,但是数据一更新,原rowid也无法再查到数据

vastbase=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
vastbase=# insert into test_rowid_update values (1,'1');
INSERT 0 1
vastbase=# select rowid rd from test_rowid_update;rd
----------------------YGoAAA==AAAAAA==AQA=
(1 行记录)vastbase=# update test_rowid_update set content='2' where rowid='YGoAAA==AAAAAA==AQA=';
UPDATE 1
vastbase=# select * from test_rowid_update where rowid='YGoAAA==AAAAAA==AQA=';id | content
----+---------
(0 行记录)vastbase=#

8.GBASE 8c

环境准备:
centos 7 x86_64

curl --proto '=https' --tlsv1.2 -sSf https://cdn-mogdb.enmotech.com/ptk/install.sh | sh
ptk checkos -o root_fix.sh
source root_fix.shuseradd gbase
su - gbasewget https://cdn.gbase.cn/products/34/_eiStkqoJ9JedVQPogBdj/GBase8cV5_5.0.0_%E4%B8%BB%E5%A4%87%E5%BC%8F_x86.zip
unzip GBase8cV5_5.0.0_主备式_x86.zip
mv  GBase8cV5_5.0.0_主备式_x86 gbase
cd gbase/Server
tar -xf GBase8cV5_S5.0.0B28_centos7.8_x86_64.tar.gz
tar -xf GBase8cV5_S5.0.0B28_CentOS_x86_64.tar.bz2
mkdir dataecho "export GAUSSHOME=/home/gbase/gbase/Server">>/home/gbase/.bash_profile &&\
echo "export PATH=\$GAUSSHOME/bin:\$PATH">>/home/gbase/.bash_profile &&\
echo "export LD_LIBRARY_PATH=\$GAUSSHOME/lib:\$LD_LIBRARY_PATH">>/home/gbase/.bash_profile &&\
echo "export PGDATA=\$GAUSSHOME/data">>/home/gbase/.bash_profile
source /home/gbase/.bash_profilegs_initdb --nodename=primary --pwpasswd=gbase@123 --encoding=UTF-8 --locale=en_US.UTF-8
gs_ctl start
gsql -r -d postgres

和vastbase一样,gbase使用了tableoid+ctid的方式,数据一更新,rowid就变了,原rowid无法再查到数据。
另外发现个差异,gbase 8c 默认plsql里执行select into 没有找到数据时不会报错,和原版openGauss不一致,不符合ORACLE的行为,需要注意。

[gbase@ha_node2 ~]$ gsql -r -d postgres
gsql ((single_node GBase8cV5 S5.0.0B28 build 51dce1ce) compiled at 2024-06-21 17:06:17 commit 0 last mr 587 )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.postgres=#  create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
postgres=# insert into test_rowid_update values (1,'1');
INSERT 0 1
postgres=# select rowid rd from test_rowid_update;rd
--------------------AAAGAAAAAAAAAAAAAA
(1 row)postgres=# update test_rowid_update set content='2' where rowid='AAAGAAAAAAAAAAAAAA';
UPDATE 1
postgres=# select * from test_rowid_update where rowid='AAAGAAAAAAAAAAAAAA';id | content
----+---------
(0 rows)postgres=#

9.神通

神通的openGauss版本没有公开下载介质,需要打电话联系客服,比较麻烦。而且也没有openGauss版本对应的文档,暂无法确认rowid的兼容程度。
对于非openGauss的版本,从公开文档中可以看到,神通数据库把ctid这个字段名直接改成了rowid,并且把数据类型修改成了bigint,从用例中的数值长度来看,应该不仅包含ctid的信息了。
http://shentongdata.com/index.php/download/list-26
神通数据库-优化及运维手册

10.UXDB

没有公开下载介质,但可以从官方文档里看到一些描述
https://www.uxsino.com/index.php/list82/82/%E4%BC%98%E7%82%AB%E6%95%B0%E6%8D%AE%E5%BA%93/0.html
优炫数据库参考手册 V2.1

UXDB数据库的rowid是为了兼容达梦rowid伪列所做功能适配,用来标识数据库基表中每一条记录的唯一键值。本次实现,还新增了数据类型:rowid。该类型是一个大范围整数的数字类型,其范围和功能等同bigint类型。
新增GUC参数:create_as_parallel。该参数的作用:控制在执行create … as或者select … into命令时,数据库可以并行的条件下,是否走并行。如果设置为off,表示为不并行,此时rowid功能正常;设置为on时,表示为走并行,此时无法保证rowid功能正常。该参数默认值为off。

这意味着UXDB的rowid也是个真正存储的一个值,而不是表示物理位置,甚至在同一个表中也还是会出现rowid重复的情况

11.瀚高

环境准备:
centos 7 x86_64

wget https://www.highgo.com/upload/download/20220708/1b73693f2c91fd7f38acbc7d3882cf6c.rpm
rpm -ivh 1b73693f2c91fd7f38acbc7d3882cf6c.rpm
su - highgo
cd $HGDB_HOME/etc
./setup primary #输入密码
pg_ctl -D /opt/HighGo6.0.4-cluster/data -l logfile start
psql #输入密码

建表就报错了,因为不支持number/varchar2类型,手动改成numeric/varchar建表成功。
然后执行匿名块又报错了,因为ORACLE的匿名块语句分隔符是 /,而PG遇到 ;就表示语句结束了。
直接select rowid from tab也是报错,没有rowid这个字段。
在pg_setting中也没有包含 rowid字样的参数。
由于官方文档内容很少,也没有搜索功能,不确认是否支持rowid。

12.TDSQL-PG(ORACLE兼容版)

没有公开下载地址,只能看文档
https://doc.fincloud.tencent.cn/tcloud/Database/TBASE/73365/19613/37492/84290

先开启参数 default_with_rowid,再建表就带rowid字段了,但是为了避免DML的性能问题,没有自动创建rowid的索引,从这个角度上看,也是真实存了数据,不是真正的物理位置。

13.海盒

没有公开下载,需要联系客服,并且没有公开的文档,无法确认rowid 的支持情况。

14.MogDB 5.2.0

环境准备:
【MogDB】MogDB5.2.0重磅发布第二篇-发布了哪些介质,如何获取?

测试记录:

  • 场景一:select * 不显示rowid
MogDB=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
MogDB=# insert into test_rowid_update values (1,'1');
INSERT 0 1
MogDB=# select * from test_rowid_update ;id | content
----+---------1 | 1
(1 row)MogDB=# drop table test_rowid_update;
DROP TABLE
MogDB=#
  • 场景二:select rowid 不报错
MogDB=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
MogDB=# insert into test_rowid_update values (1,'1');
INSERT 0 1
MogDB=# select rowid,t.rowid,t.* from test_rowid_update t ;rowid       |      rowid       | id | content
------------------+------------------+----+---------AAAAAAEAAADsVAAA | AAAAAAEAAADsVAAA |  1 | 1
(1 row)MogDB=# drop table test_rowid_update;
DROP TABLE
MogDB=#
  • 场景三:通过rowid快速检索数据
MogDB=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
MogDB=# insert into test_rowid_update select id,'id_'||id from generate_series(1,1000) id;
INSERT 0 1000
MogDB=# vacuum test_rowid_update;
VACUUM
MogDB=# vacuum test_rowid_update;
VACUUM
MogDB=# explain analyze select  t.* from test_rowid_update t where rowid = (select rowid from test_rowid_update  where content='id_50') ;QUERY PLAN
---------------------------------------------------------------------------------------------------------------------Tid Scan on test_rowid_update t  (cost=12.13..16.14 rows=1 width=450) (actual time=0.272..0.273 rows=1 loops=1)TID Cond: (rowid = $0)InitPlan 1 (returns $0)->  Seq Scan on test_rowid_update  (cost=0.00..12.12 rows=1 width=12) (actual time=0.040..0.261 rows=1 loops=1)Filter: ((content)::text = 'id_50'::text)Rows Removed by Filter: 999Total runtime: 0.407 ms
(7 rows)MogDB=# drop table test_rowid_update;
DROP TABLE
MogDB=#

可以看到这里使用rowid作为where条件时,使用的是Tid Scan,和使用ctid作为where条件时,执行计划是一样的,也就是通过物理位置进行快速检索。

  • 场景四:对同一个rowid进行多次更新
MogDB=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
MogDB=# insert into test_rowid_update values (1,'1');
INSERT 0 1
MogDB=# declare
MogDB-# i int;
MogDB-# begin
MogDB$# for rec in (select rowid rd from test_rowid_update) loop
MogDB$# update test_rowid_update set content='2' where rowid=rec.rd;
MogDB$# update test_rowid_update set content='3' where rowid=rec.rd;
MogDB$# end loop;
MogDB$# select 1 into i from test_rowid_update where id=1 and content='3';
MogDB$# end;
MogDB$# /
ANONYMOUS BLOCK EXECUTE
MogDB=# select * from test_rowid_update where  id=1 and content='3';id | content
----+---------1 | 3
(1 row)MogDB=# drop table test_rowid_update ;
DROP TABLE
MogDB=#

从这里可以看到,该行数据用相同的rowid作为更新条件,能正常进行多次更新。
MogDB的rowid同样也是基于tableoid+ctid分别进行base64编码,在update后也会变,但是仍旧可以用之前的rowid找到变更后的这行记录,所以对一行进行多次更新也不会有问题(建议在一个事务内完成,避免vacuum释放掉历史ctid)。

MogDB=# create table test_rowid_update(id number,content varchar2(200));
CREATE TABLE
MogDB=# \dS+ test_rowid_updateTable "public.test_rowid_update"Column  |          Type          | Modifiers | Storage  | Stats target | Description
---------+------------------------+-----------+----------+--------------+-------------id      | numeric                |           | main     |              |content | character varying(200) |           | extended |              |
Has OIDs: no
Options: orientation=row, compression=noMogDB=# insert into test_rowid_update values (1,'1');
INSERT 0 1
MogDB=# select rowid rd from test_rowid_update;rd
------------------AAAAAAEAAADPWAAA
(1 row)MogDB=# update test_rowid_update set content='2' where rowid='AAAAAAEAAADPWAAA';
UPDATE 1
MogDB=# select * from test_rowid_update  where rowid='AAAAAAEAAADPWAAA';id | content
----+---------1 | 2
(1 row)MogDB=# update test_rowid_update set content='3' where rowid='AAAAAAEAAADPWAAA';
UPDATE 1
MogDB=# select * from test_rowid_update  where rowid='AAAAAAEAAADPWAAA';id | content
----+---------1 | 3
(1 row)MogDB=# select rowid,* from test_rowid_update  where rowid='AAAAAAEAAADPWAAA';rowid       | id | content
------------------+----+---------AAAAAAMAAADPWAAA |  1 | 3
(1 row)
  • 场景五:删除表中重复记录
MogDB=# create table test_rowid_update as select id,'n_'||id as content from generate_series(1,10) id;
INSERT 0 10
MogDB=# insert into test_rowid_update select id,'d_'||id from generate_series(1,5) id;
INSERT 0 5
MogDB=# DELETE FROM test_rowid_update t1
MogDB-# WHERE t1.rowid > (
MogDB(# SELECT MIN(t2.rowid)
MogDB(# FROM test_rowid_update t2
MogDB(# WHERE t1.id= t2.id
MogDB(# );
DELETE 5
MogDB=# select * from test_rowid_update;id | content
----+---------1 | n_12 | n_23 | n_34 | n_45 | n_56 | n_67 | n_78 | n_89 | n_910 | n_10
(10 rows)MogDB=#

正确删除了指定字段的重复行

四、测试结果汇总

数据库是否增加了物理存储字段select * 不显示rowidselect rowid 不报错通过rowid快速检索数据对同一个rowid进行多次更新删除表中重复记录
DM8Y/NYYYYY
崖山 23.2.4NYYYYY
OCEANBASE 4.1YYYYYY
KINGBASE 8YYYYYY
POLARDB-O 2.0YYYYYY
TDSQL-PG(Oracle兼容版)YYYNYY
UXDBY?????
神通(openGauss版)??????
海盒??????
瀚高 6.0.4??????
GAUSSDB 503.1.0.SPC1700NYNNNN
OPENGAUSS 6.0NYNNNN
GBASE 8cNYYYNY
VASTBASE G100 V2.2 BUILD 16NYYYNY
MogDB 5.2.0NYYYYY

五、总结

PG/OG系最佳的rowid实现方案,在astore下必然无法实现,所以OG系的ustore应该是当下最佳实现方案,但ustore仍然还需要一段时间来进行市场验证。因此MogDB5.2.0在astore下实现的这个rowid,在一众PG/OG系的解决方案里,属于是一种全新的方案了,这种方案不仅没有让DML性能下降,又可以比同样DML性能没有下降的其他数据库支持更多的场景,是PG/OG系中已知的目前唯一一款在astore下没有新增物理字段又同时支持了这5个rowid使用场景的数据库。

声明:本文不涉及任何商业行为,仅对自测结果进行客观陈述,如果觉得有不妥当,请联系本人进行修改 darkathena@qq.com

  • 本文作者: DarkAthena
  • 本文链接: https://www.darkathena.top/archives/mogdb-5.2.0-support-rowid
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/56705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scala 高阶函数(2)上

学习目录 一.reduce reduce的含义 idea实例 二.reduceLeft-reduceRight reduceLeft-reduceRight的含义 idea实例 练习:求最值

word建立目录以及修改页码

1、为word建立新的目录 (1)选中word中的标题设置为第几级标题,将所有的标题均设置完成。最后可以鼠标右击标题,对不同的标题字体大小等进行设置。右击-->修改-->格式-->段落 (2)在word中插入新的…

【多模态大模型】 端侧多模态模型 Qwen2-VL-2B-Instruct

【多模态大模型】 端侧多模态模型 Qwen2-VL-2B-Instruct Qwen2-VL-2B-Instruct 模型介绍模型测评运行环境安装运行模型Image Resolution for performance boosttwo methods for fine-grained control over the image size input to the model: 下载开源协议参考 Qwen2-VL-2B-In…

专题十二_floodfill(洪水灌溉)算法_算法专题详细总结

目录 1. 图像渲染(medium) 解析: 函数头: 函数体:固定模板 设置全局变量: 总结: 2. 岛屿数量(medium) 解析: 注意: 总结: …

利用由 Search AI 提供支持的自动导入功能加速 Elastic Observability 中的日志分析

作者:来自 Elastic Bahubali Shetti 通过自动化自定义数据集成,以创纪录的速度将日志迁移到 AI 驱动的日志分析。 Elastic 正在通过自动提取自定义日志来加速采用 AI 驱动的日志分析(AI-driven log analytics),随着基…

时间序列预测(六)——循环神经网络(RNN)

目录 一、RNN的基本原理 1、正向传播(Forward Pass): 2、计算损失(Loss Calculation) 3、反向传播——反向传播通过时间(Backpropagation Through Time,BPTT) 4、梯度更新&…

Flink时间语义和时间窗口

前言 在实际的流计算业务场景中,我们会发现,数据和数据的计算往往都和时间具有相关性。 举几个例子: 直播间右上角通常会显示观看直播的人数,并且这个数字每隔一段时间就会更新一次,比如10秒。电商平台的商品列表&a…

MySQL-15.DQL-分页查询

一.DQL-分页查询 -- 分页查询 -- 1. 从 起始索引0 开始查询员工数据,每页展示5条记录 select * from tb_emp limit 0,5; -- 2.查询 第1页 员工数据,每页展示5条记录 select * from tb_emp limit 0,5; -- 3.查询 第2页 员工数据,每页展示5条记…

6.计算机网络_UDP

UDP的主要特点: 无连接,发送数据之前不需要建立连接。不保证可靠交付。面向报文。应用层给UDP报文后,UDP并不会抽象为一个一个的字节,而是整个报文一起发送。没有拥塞控制。网络拥堵时,发送端并不会降低发送速率。可以…

Chromium 前端window对象c++实现定义

前端中window.document window.alert()等一些列方法和对象在c对应定义如下: 1、window对象接口定义文件window.idl third_party\blink\renderer\core\frame\window.idl // https://html.spec.whatwg.org/C/#the-window-object// FIXME: explain all uses of [Cros…

git 报错 SSL certificate problem: certificate has expired

git小乌龟 报错 SSL certificate problem: certificate has expired 场景复现: 原因: 这个错误表明你在使用Git时尝试通过HTTPS进行通信,但是SSL证书已经过期。这通常发生在使用自签名证书或证书有效期已到期的情况下。 解决方法: 1.如果是…

【思维导图】C语言—常见概念

hello,友友们,今天我们进入一个新的专栏——思维导图! 思维导图帮助我们复习知识的同时建构出一个清晰的框架,我往后会不断更新各个专栏的思维导图,关注我,一起加油! 今天我们回顾C语言中的常见…

智慧社区服务平台:基于Spring Boot的实现

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理基于web的智慧社区设计与实现的相关信息成…

意外发现!AI写作这样用,热点文章轻松超越同行90%!

做自媒体,写热点文章很重要。 热点自带流量,能很快吸引不少读者。 可很多自媒体新手很犯愁。 干货文还能勉强写出来,碰到热点文就不知咋办了。 为啥写热点文章这么难呢? 关键是得找个新颖角度切入。 要是只在网上反复复制粘贴那些…

R语言机器学习算法实战系列(九)决策树分类算法 (Decision Trees Classifier)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍教程下载数据加载R包导入数据数据预处理数据描述数据切割调节参数构建模型模型的决策树预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve特征的重要性保存模…

Spring Boot技术栈的电影评论网站设计与实现

6系统测试 6.1概念和意义 测试的定义:程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为: 目的:发现程序的错误; 任务:通过在计算机上执行程序,暴露程序中潜在的错误。 另一个…

基于手机模拟器开发游戏辅助的技术选择

开发基于手机模拟器的游戏辅助工具是一项复杂且具有挑战性的任务。为了帮助开发人员选择适合的技术方案并提供详尽的开发指导,我们将从以下几个方面进行分析:发展背景、技术选型、实现原理、实际案例和相关的法律与道德考量。 1. 发展背景 随着智能手机…

Android--第一个android程序

写在前边 ※安卓开发工具常用模拟器汇总Android开发者必备工具-常见Android模拟器(MuMu、夜神、蓝叠、逍遥、雷电、Genymotion...)_安卓模拟器-CSDN博客 ※一般游戏模拟器运行速度相对较快,本文选择逍遥模拟器_以下是Android Studio连接模拟器实现(先从以上博文中…

C++初阶(五)--类和对象(中)--默认成员函数

目录 一、默认成员函数(Default Member Functions) 二、构造函数( Constructor) 1.构造函数的基本概念 2.构造函数的特征 3.构造函数的使用 无参构造函数 和 带参构造函数 注意事项: 4.默认构造函数 隐式生成的…

Node-RED开源项目的modbus通信(TCP)

一、Modbus 通信协议 Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De fact…