深入解析KingbaseES中的行标识符:OID与ROWID
在数据库这个领域里,咱们都知道,怎么给每一行数据一个独一无二的"身份证",是保证数据靠谱不混乱、操作流畅又高效的根本。KingbaseES(KES)作为咱们自家的国产数据库,在处理这个事儿上有不少自己的门道儿。其中,对象标识符(OID)和行标识符(ROWID)就是它内部管理和元数据访问的两员"大将"。
今天这篇分享,我就从技术实现的角度,带大家把KingbaseES里OID和ROWID这俩概念的底层原理给掰扯清楚。咱们一起来看看它们各自都有啥特点、适合用在哪些场合,还有它们之间那些微妙的"关系"。我会详细说说OID在系统表和用户表里表现为啥不一样,以及KES特有的ROWID机制,包括它的数据类型、操作规范,还有它俩在GUC参数配置上可能闹的"小矛盾"。当然啦,咱们还会把OID、ROWID和大家更熟悉的自增主键放一块儿比一比,再瞅瞅怎么用这些标识符来查询和解析数据库的元数据。希望通过我这篇唠嗑式的分享,能帮大家对KingbaseES行标识符管理的技术细节有个更全面的认识,往后在数据库设计、开发和优化的时候,也能做得更明白、更到位。 
@[toc]
1. KingbaseES中的对象标识符(OID)
在数据库系统里头,给每一行数据一个唯一的身份标识,这活儿是核心中的核心。KingbaseES(KES)在这方面提供了好几种方法,其中对象标识符(OID)就是它内部管理和元数据访问的一个重要角色。
1.1 OID概述
OID(Object Identifier),翻译过来就是对象标识符,它是KingbaseES内部用来给数据库对象(比如表、视图、存储过程这些)和数据行打标签的一个4字节长的标识符。在KES里头,系统表和视图天生就带着OID,而且还把它当主键用。不过话说回来,对于咱们自己建的普通用户表,OID默认可是不会露脸的,也不是所有表都自动配有这玩意儿。
KES版本验证: 我写这篇东西的时候,是基于下面这个KingbaseES版本做的验证:
sql
select version();

1.2 OID的创建与可见性
咱们自己建的普通表,默认可是没有OID的。如果你想让某个表带上OID,有两种方法:一个是在建表的时候用上WITH OIDS这个子句,另一个是把GUC参数default_with_oids给设置成true。
示例:默认情况下普通表不带OID
sql
create table tt5(id int);
insert into tt5 values(10);
select oid,id from tt5;

从上边这个例子咱们就能看出来,直接去查tt5表的oid列会报错,这说明这列压根儿就不存在。
示例:通过设置default_with_oids启用OID
sql
set default_with_oids to true;
create table tt6(id int);
insert into tt6 values(10);
select oid from tt6;
select * from tt6;

当default_with_oids被设置成true之后,新创建的tt6表就自动有了OID。虽然你用select *是看不到OID列的,但直接查询oid这个伪列是没问题的。
示例:通过CREATE TABLE ... WITH OIDS启用OID
sql
set default_with_oids to false;
create table tt7(id int) with oids;
insert into tt7 values(10);
select oid,id from tt7;

哪怕default_with_oids是false,用WITH OIDS这个子句照样可以给指定的表配上OID。
1.3 OID的范围特性:全局与局部
OID在KingbaseES里头,它的"地盘"大小可不太一样,理解这一点对咱们搞清楚它该用在哪很重要。
系统表中的OID:全局且连续 对于系统表来说,OID是全局唯一的,而且分配的时候大体上是连续的。这就意味着,不同系统表里的对象,它们的OID值可能是挨着的。
sql
---创建一个自定义集合类型,查看其在sys_type 中的OID
create type aatyp is table of int;
select oid,typname from sys_type where typname = 'aatyp';
---创建一个自定义函数,查看其在sys_proc 中的OID
create or replace function func_test05(i int)
returns int
as $$
begin
return 1;
end;
$$ language plpgsql;
select oid,proname from sys_proc where proname = 'func_test05';

从上面这个例子咱们就能发现,新创建的类型aatyp和函数func_test05在它们各自的系统表sys_type和sys_proc里,拿到的OID是连着的(55136和55137),这正好印证了系统表OID的全局连续性。
普通表中的OID:局部 跟系统表不一样,KingbaseES里普通表的OID是"各自为政"的,也就是说,每个普通表都有自己的OID序列,跟别的表不掺和。这意味着哪怕两个不同的普通表都启用了OID,它们的OID序列也是各自从1开始重新计数的。
1.4 OID的特性与使用考量
- 顺序分配与潜在重复: OID是挨着顺序分配的4字节整数。虽然说在整个数据库实例里头,最开始的时候它确实是唯一的,但这个计数器大概数到42.9亿左右的时候,就有可能转回来重新开始,出现重复。
- 唯一性保障: 要是担心单个表里头的OID出现重复,你可以在OID列上建一个唯一索引。系统在插入新行的时候会检查OID是不是唯一的,如果发现重复了,它会重新给你生成一个,直到找到不重复的为止。不过话又说回来,如果表里的数据量特别大,这个反复尝试的过程效率可就高不到哪儿去了。
- 推荐实践: 对于用户表里头需要唯一行编号的情况,官方建议咱们用
SERIAL或者BIGSERIAL这种数据类型来当主键,别太依赖OID。SERIAL适合估计数据量不会超过20亿的表,而BIGSERIAL呢,则是给那些数据量可能超过20亿的表准备的,它能提供更靠谱的唯一性保证。
1.5 regclass:OID的便捷别名
regclass这个数据类型挺特别的,它能让咱们直接用对象的名字来引用它的OID,这样一来,查询系统元数据可就方便多了。像表、索引、视图这些对象的标识符,说白了就是系统表sys_class里头oid字段的值。
为了给大家演示regclass怎么用,我先建一个示例表teachers:
sql
CREATE TABLE teachers (
teacher_id INT PRIMARY KEY,
teacher_name VARCHAR(100),
age INT,
sal INT,
gender VARCHAR(10),
title VARCHAR(100),
position VARCHAR(100),
department VARCHAR(100)
);
INSERT INTO teachers (teacher_id, teacher_name, age, sal, gender, title, position, department) VALUES
(1, '张老师', 35, 8000, '男', '教授', '系主任', '计算机科学'),
(2, '李老师', 42, 9500, '女', '副教授', '教研室主任', '软件工程'),
(3, '王老师', 28, 6000, '男', '讲师', '辅导员', '信息管理');
示例:查询sys_class获取表OID
sql
SELECT oid FROM sys_class WHERE relname = 'teachers';
示例:使用regclass转换OID到表名
sql
---查询标识符(OID)为16700的表名
select 16700::regclass;
通过::regclass这个类型转换,咱们就能直接把OID变成对应的对象名称,省事儿!
示例:用regclass简化元数据查询 以前那种老方法,要查表的字段信息,得把sys_attribute和sys_class这两个表关联起来查:
sql
SELECT attrelid,attname,atttypid,attlen, attnum,attnotnull
FROM sys_attribute
WHERE attrelid = (SELECT oid FROM sys_class WHERE relname = 'teachers');
但要是用上regclass类型转换,这个查询就能变得简洁多了:
sql
SELECT
attname,
atttypid,
attlen,
attnum,
attnotnull
FROM
sys_attribute
WHERE
attrelid = 'teachers'::regclass;

这里的'teachers'::regclass实际上跟SELECT oid FROM sys_class WHERE relname='teachers'是一个意思,它返回的就是teachers表的OID,这样一来,元数据查询的写法可就清爽多了。
2. KingbaseES中的行标识符(ROWID)
除了OID,KingbaseES还整了个ROWID机制,专门用来给数据库里每一条记录当"身份证"。ROWID是个伪列,它在逻辑上给每一行数据一个唯一标识,但不像普通列那样实实在在地存在表里头。虽然咱们能查到ROWID的值,但不能直接往里插、改或者删。
2.1 ROWID的创建方式
KingbaseES提供了多种方式来为表启用ROWID:
-
GUC参数
default_with_rowid: 当此参数设置为true时,所有新创建的表都会自动增加一个名为"ROWID"的隐含列,其类型为ROWID TYPE。所有插入的数据,其ROWID都会被写入到该列中。示例:通过GUC参数启用ROWID
sql
set default_with_rowid to true; create table tt_rowid_guc(id int); insert into tt_rowid_guc values(10); select rowid,id from tt_rowid_guc;
sql
2. **`CREATE TABLE ... WITH ROWID`语句:**
如果不想全局启用ROWID,可以在创建特定表时使用`WITH ROWID`子句来为其添加ROWID列。
**示例:通过`CREATE TABLE ... WITH ROWID`创建**
```sql
create table student(sno int, name varchar(10), birthday date,
department varchar(10), sex varchar(10))
with rowid;
insert into student values(1, 'li', '2018-1-1', 'physics', 'boy');
insert into student values(5, 'lu', '2018-1-2', 'chinese', 'boy');
select rowid, * from student;
css
有个地方得提一下,当表创建了ROWID之后,KingbaseES会默认给它建一个带唯一约束的B-tree索引,这样查询性能就能上去。
```sql
\d student
sql
3. **`ALTER TABLE ... SET WITH ROWID`语句:**
对于已经存在的表,可以通过`ALTER TABLE`语句来添加ROWID列。
**示例:对已有表添加ROWID**
```sql
create table existing_table(id int);
alter table existing_table set with rowid;
insert into existing_table values(1);
select rowid, id from existing_table;
2.2 ROWID与OID的参数治理冲突
在KingbaseES里头,default_with_rowid和default_with_oids这俩GUC参数都是管表是不是默认带行标识符的。不过话说回来,它们俩不能同时起作用,default_with_rowid这个参数的优先级比default_with_oids要高。
示例:参数冲突时的行为
sql
-- 检查当前参数设置
show default_with_oids;
show default_with_rowid;
-- 在两个参数都为on的情况下创建表
create table tt_conflict(id int);
insert into tt_conflict values(10);
-- 查询ROWID,成功
select rowid,id from tt_conflict;
-- 查询OID,失败
select oid,id from tt_conflict;
从上述示例可以看出,尽管default_with_oids为on,但由于default_with_rowid也为on,新创建的表tt11会默认带有ROWID,而不会带有OID,这表明ROWID的优先级更高。
还有啊,如果default_with_rowid是false而default_with_oids是true,这时候你还想用CREATE TABLE ... WITH ROWID,系统可是会报错的。
sql
```sql
set default_with_rowid to false;
set default_with_oids to true;
create table tt_explicit_rowid(id int) with rowid;
这个错误信息明确指出,在default_with_rowid为false且default_with_oids为true的情况下,不能显式地创建带有ROWID的表。
2.3 ROWID数据类型深度解析
KingbaseES的ROWID类型数据表示行记录在数据库中的逻辑唯一标识。它并非物理地址,而是通过内部复合结构存储,并通过64进制字符进行表示。
- 表示形式: ROWID通常以23个字符的64进制字符串表示,包含A-Z, a-z, 0-9, +以及/符号。
- 存储方式: 实际存储采用变长方式,占用4到18个字节。
- 内部结构: ROWID类型的数据通过内部复合结构存储,包含以下信息:
- 事务的回卷次数(0-5位)
- 元组插入时的XID(6-11位)
- 事务内已插入元组的个数(12-22位)
- 编码格式: 事务回卷次数和XID采用32位编码,事务内元组个数采用64位编码。
- ROWID范围:
- Min:
AAAAAA AAAAAB AAAAAAAAAAA - Max:
D////// D////// P//////////超出此范围的ROWID被视为非法格式。
- Min:
- 事务内元组计数: 每次开启新的事务(包括子事务),事务内已插入元组的个数都会重新计算。
示例:ROWID的导入与导出
sql
CREATE TABLE rowid_tt1(id rowid);
-- 导入ROWID
\echo `echo 'AAAAAAAAAAABAAAAAAAAAAA' > /tmp/rowid_tt1.txt`
COPY rowid_tt1 FROM '/tmp/rowid_tt1.txt';
select * from rowid_tt1;
-- 导出ROWID
copy rowid_tt1 to '/tmp/rowid_tt1_to.txt';
\echo `more /tmp/rowid_tt1_to.txt`
示例:ROWID数据类型校验 ROWID的字符数必须是23个,否则无法正常插入。
sql
insert into rowid_tt1 values('AAAAAAAAAAABAAAAAAAAAAA44444444');
insert into rowid_tt1 values('AAAAAAAAAAABAAAAA');
2.4 ROWID的操作与使用注意事项
ROWID支持特定的操作符和使用场景:
- 投影列: 支持在
SELECT语句中作为投影列,查询当前行的逻辑ID。 - 过滤条件: 支持在
WHERE子句中使用ROWID进行条件过滤,例如ROWID OP CONST或CONST OP ROWID的形式,其中OP只支持关系运算符(=,>,>=,<,<=,!=等)。 - 排序与分组: 支持在
ORDER BY和GROUP BY子句中使用ROWID。 - 存储过程: 可以在存储过程中结合上述1、2、3点使用。
- 不支持运算: ROWID不支持与关系运算符以外的其他运算符进行运算。
- 索引支持: ROWID支持BTREE和HASH索引,这有助于提高基于ROWID的查询性能。
示例:ROWID的比较操作
sql
select * from rowid_tt1;
select * from rowid_tt1 where id >= 'AAAAAAAAAAABAAAAAAAAAAB';
原则上,后插入的数据的ROWID要大于先插入的ROWID,即ROWID属于单调递增的数据。
3. 核心存储机制对比:OID、ROWID与自增主键
在KingbaseES里头,给行加标识符有好几种方法,每种方法设计的时候都有自己特定的目的,适合用在不同场合。咱们要是能把OID、ROWID还有自增主键(比如SERIAL/BIGSERIAL)这仨之间的相同点和不同点搞清楚,对数据库设计和性能优化来说,那可是相当重要的。
3.1 OID (Object Identifier)
- 定义与特性: OID是KingbaseES内部用来给数据库对象和数据行打标签的4字节整数。它在系统表里当主键用,具有全局唯一性。但如果是用户表,要是通过
WITH OIDS或者default_with_oids给启用了,那它的OID可就只在这一个表里有效了,而且等数到42.9亿左右的时候,还可能转回来重复。 - 存储: OID作为伪列存在,如果启用,会为每行分配一个4字节的存储空间。
- 唯一性与可靠性: 理论上全局唯一,但对于用户表,其局部性及潜在的重复风险使其不适合作为业务主键。虽然可以通过唯一索引强制唯一,但这会带来性能开销。
- 主要用途: 主要用于系统内部管理和元数据访问,例如通过
regclass类型快速查询对象信息。不推荐作为用户表的业务主键。
3.2 ROWID (Row Identifier)
- 定义与特性: ROWID是KingbaseES特有的逻辑行标识符,它是一个伪列,为每行提供一个唯一的、单调递增的标识。ROWID的值是64进制字符串表示,内部结构包含事务信息,但它并非物理地址。
- 存储: ROWID不直接存储在表中,但其逻辑存在需要内部机制维护,实际存储占用4-18字节。
- 唯一性与可靠性: 在KingbaseES中,ROWID是唯一的,并且默认会为其创建唯一B-tree索引,保证了其唯一性和查询效率。其单调递增的特性在某些场景下有优势。
- 主要用途: 提供了一种高效的行访问机制,尤其适用于需要快速定位和操作单行数据的场景。可以作为一种内部的、高效的行引用方式,但由于其伪列特性,不适合作为业务主键。
3.3 自增主键 (SERIAL/BIGSERIAL)
- 定义与特性:
SERIAL和BIGSERIAL是KingbaseES提供的一种方便创建自增整数列的伪类型,它们实际上是INTEGER和BIGINT类型,并自动关联一个序列(sequence)对象,确保插入新行时自动生成唯一的、递增的值。 - 存储: 作为普通列存储在表中,占用4字节(
SERIAL)或8字节(BIGSERIAL)。 - 唯一性与可靠性: 由序列保证全局唯一性,是业务主键的最佳选择。
SERIAL支持20亿条记录,BIGSERIAL支持更大的数据量。 - 主要用途: 广泛用于用户表,作为业务主键,提供稳定、可靠、易于理解的行标识。
3.4 机制对比总结
为了方便大家对比,我把这仨机制的主要特点整理成下面这个表格:
| 特性 | OID (Object Identifier) | ROWID (Row Identifier) | 自增主键 (SERIAL/BIGSERIAL) |
|---|---|---|---|
| 类型 | 4字节整数 | 64进制字符串表示,内部复合结构(4-18字节) | 4字节整数 (SERIAL) / 8字节整数 (BIGSERIAL) |
| 存储 | 伪列,如果启用则占用存储 | 伪列,逻辑存在,内部机制维护 | 普通列,实际存储在表中 |
| 唯一性 | 系统表全局唯一;用户表局部唯一,可能重复 | 逻辑唯一,默认有唯一索引保证 | 全局唯一,由序列保证 |
| 可见性 | 伪列,需显式查询 | 伪列,需显式查询 | 普通列,直接可见 |
| 可操作性 | 不可直接修改 | 不可直接修改 | 可作为普通列操作(但通常不建议手动修改自增值) |
| 优先级 | 低于ROWID(当GUC参数冲突时) | 高于OID(当GUC参数冲突时) | 独立于OID和ROWID |
| 推荐用途 | 系统内部管理,元数据查询 | 高效行访问,内部行引用 | 用户表业务主键,提供稳定可靠的行标识 |
| 性能 | 查找效率一般,重复风险需额外索引 | 默认有唯一B-tree索引,查找效率高 | 查找效率高,通常作为聚簇索引或主键索引的一部分 |
3.5 什么时候该选哪种机制
-
选自增主键(
SERIAL/BIGSERIAL):- 首选方案: 所有用户业务表,我都强烈建议用自增主键来当行的唯一标识。它给咱们的保证最稳定、最靠谱,而且管理和理解起来也简单。
- 数据量考量: 得根据你估计的数据量来选是用
SERIAL还是BIGSERIAL,别等到数据溢出了才后悔。
-
选ROWID:
- 特定场景优化: 当你需要一种高效、内部的行引用机制,又不想让它掺和到业务逻辑里头去的时候,可以考虑用ROWID。比如说,某些内部工具或者临时查询需要快速找到并操作某一行,用它就挺合适。
- 性能敏感: ROWID天生就带着唯一索引,在那些需要通过行标识符快速查找的场景里,它可能比那些没索引的普通列要快不少。
- 兼容性需求: 如果你的应用是从别的数据库系统迁移过来的,而且原来的应用依赖类似的行标识符概念,那ROWID可能能提供更好的兼容性。
-
别用OID当用户表的主键:
- 不推荐: 虽然能给用户表启用OID,但因为它"各自为政"的特性、可能重复的风险,还有不如自增主键那么靠谱的唯一性,我不建议把它拿来当用户表的业务主键。它的主要价值还是在系统元数据管理那块儿。
把这三种行标识机制的特点和适用范围搞明白了,咱们开发者就能根据具体的业务需求和性能考虑,在KingbaseES里做出聪明的选择,从而搭出既高效又稳当的数据库应用。
4. 元数据访问与系统表解析
KingbaseES作为一款关系型数据库,它内部维护着一大堆元数据,专门用来描述数据库对象的结构、属性和它们之间的关系。这些元数据都存放在系统表里头,而OID和regclass类型在咱们访问和解析这些元数据的时候,可是起着关键作用的。
4.1 深入理解系统表
KingbaseES的系统表是数据库的"数据字典",记录了所有数据库对象的详细信息。以下是一些与对象标识符和元数据查询密切相关的系统表:
sys_class: 存储了所有表、索引、视图等关系对象的元数据。每个关系对象在sys_class中都有一条记录,其oid列就是该对象的唯一标识符。sys_attribute: 存储了所有列(属性)的元数据。每条记录描述了一个表的某个列,通过attrelid(关联关系OID)字段与sys_class中的对象关联。sys_type: 存储了所有数据类型的元数据。sys_proc: 存储了所有函数和存储过程的元数据。
4.2 利用OID和regclass进行元数据查询
regclass类型是KingbaseES提供的一种便捷机制,它允许用户通过对象的名称来引用其OID,从而简化了对系统表的查询。
示例:查询表的OID 要获取一个表的OID,最直接的方式是查询sys_class表:
sql
SELECT oid FROM sys_class WHERE relname = 'teachers';
使用regclass类型转换,可以更简洁地实现相同目的:
sql
test=# SELECT 'teachers'::regclass;
虽然直接输出的是表名,但其内部表示就是该表的OID。在需要OID作为参数的查询中,这种转换非常有用。
示例:查询表的列信息 假设我们需要查询teachers表的所有列的详细信息,包括列名、数据类型OID、长度、列号等。
传统方式(需要子查询或JOIN):
sql
SELECT attrelid,attname,atttypid,attlen, attnum,attnotnull
FROM sys_attribute
WHERE attrelid = (SELECT oid FROM sys_class WHERE relname = 'teachers');
使用regclass简化查询:
sql
SELECT
attname,
atttypid,
attlen,
attnum,
attnotnull
FROM
sys_attribute
WHERE
attrelid = 'teachers'::regclass;
这里的'teachers'::regclass实际上等同于SELECT oid FROM sys_class WHERE relname='teachers',它返回了teachers表的OID,从而实现了更简洁的元数据查询。
示例:查询数据类型信息 类似地,我们可以查询特定数据类型的OID或名称:
sql
-- 查询integer类型的OID
SELECT 'integer'::regtype;
-- 查询OID为1700的数据类型名称
SELECT 1700::regtype;
4.3 元数据访问的意义
- 数据库管理: 数据库管理员可以利用这些系统表和OID/
regclass机制来监控数据库状态、诊断问题、管理权限和优化性能。 - 应用开发: 开发者可以编写动态SQL或工具,根据数据库的元数据自动调整应用行为,例如生成ORM映射、数据迁移脚本或报表。
- 审计与合规: 通过查询系统表,可以获取对象的创建时间、修改历史、所有者等信息,有助于满足审计和合规性要求。
所以说,OID和regclass类型是KingbaseES里访问和解析元数据的两把"利器"。它们给咱们提供了一种既高效又灵活的方法,来跟数据库的内部结构打交道,这对于咱们深入理解、有效管理KingbaseES数据库来说,可是至关重要的。
5. 兼容性与参数治理(GUC参数冲突)
KingbaseES通过GUC(Grand Unified Configuration)参数给了咱们很灵活的配置选项,让咱们能根据具体需求来调整数据库的行为。在处理行标识符这方面,default_with_oids和default_with_rowid是两个挺关键的GUC参数,它们管着新创建的表是不是默认带上OID或者ROWID。搞明白这些参数是怎么交互的、冲突了怎么解决,对于数据库管理员和开发者来说,要想把参数治理好,这可是很重要的。
5.1 行标识符相关的GUC参数
-
default_with_oids:- 作用: 当此参数设置为
true时,所有新创建的表将默认包含一个OID伪列。 - 默认值: 通常为
false。 - 影响: 启用后,用户表将拥有OID,但如前所述,其局部性和潜在重复风险使其不适合作为业务主键。
- 作用: 当此参数设置为
-
default_with_rowid:- 作用: 当此参数设置为
true时,所有新创建的表将默认包含一个ROWID伪列。 - 默认值: 通常为
false。 - 影响: 启用后,用户表将拥有ROWID,并自动创建唯一B-tree索引,提供高效的行访问能力。
- 作用: 当此参数设置为
5.2 GUC参数冲突解决机制
KingbaseES在处理default_with_oids和default_with_rowid这两个参数的冲突时,遵循明确的优先级规则:
ROWID参数优先级高于OID参数。
这意味着,如果两个参数都被设置为true,KingbaseES会优先为新创建的表启用ROWID,而忽略default_with_oids的设置。
示例:参数冲突时的行为
sql
-- 检查当前参数设置
show default_with_oids;
show default_with_rowid;
-- 在两个参数都为on的情况下创建表
create table tt_conflict(id int);
insert into tt_conflict values(10);
-- 查询ROWID,成功
select rowid,id from tt_conflict;
-- 查询OID,失败
select oid,id from tt_conflict;
从上述示例可以看出,尽管default_with_oids为on,但由于default_with_rowid也为on,新创建的表tt11会默认带有ROWID,而不会带有OID,这表明ROWID的优先级更高。
显式WITH ROWID与GUC参数的交互
当default_with_rowid为false且default_with_oids为true时,如果尝试使用CREATE TABLE ... WITH ROWID语句,KingbaseES会报错。这是因为在当前GUC参数配置下,系统默认会为表创建OID,而用户又显式要求创建ROWID,这与GUC参数的优先级规则相悖。
示例:显式WITH ROWID与GUC参数的冲突
sql
set default_with_rowid to false;
set default_with_oids to true;
create table tt_explicit_rowid(id int) with rowid;
这个错误信息明确指出,在default_with_rowid为false且default_with_oids为true的情况下,不能显式地创建带有ROWID的表。
5.3 参数配置的最佳实践
为了避免不必要的冲突和混淆,建议在KingbaseES中进行参数配置时遵循以下最佳实践:
- 明确需求: 在决定是否启用
default_with_oids或default_with_rowid之前,应明确应用程序对行标识符的需求。- 如果需要高效的内部行引用机制,并且接受其伪列特性,可以考虑启用
default_with_rowid。 - 如果仅依赖系统内部的OID进行元数据管理,且不希望用户表默认带有额外的标识符,则保持
default_with_oids为false。
- 如果需要高效的内部行引用机制,并且接受其伪列特性,可以考虑启用
- 避免同时启用: 鉴于
default_with_rowid的优先级,通常不建议同时将default_with_oids和default_with_rowid都设置为true,以避免潜在的混淆和不确定性。 - 优先使用自增主键: 对于用户业务表,始终优先使用
SERIAL或BIGSERIAL作为主键,而不是依赖OID或ROWID。自增主键提供了最可靠的唯一性保证和最佳的业务语义。 - 表级控制: 如果只需要为少数特定表启用ROWID,而不是全局启用,则应将
default_with_rowid保持为false并在创建这些表时显式使用WITH ROWID子句。 - 文档记录: 对于生产环境中的GUC参数配置,应进行详细的文档记录,包括每个参数的设置原因和预期效果,以便于后续的维护和故障排查。
通过合理的参数治理,可以确保KingbaseES数据库在行标识符方面能够满足应用程序的需求,同时保持数据库的稳定性和可维护性。
总结
咱们今天把KingbaseES里头的OID和ROWID这俩行标识符机制聊了个透,能看出来它们各有各的侧重点,适合用在不同的地方。
OID 作为KingbaseES内部的对象标识符,在系统元数据管理这块儿可是个关键角色,它保证了数据库内部对象的一致性和可追溯性。不过对于咱们平时用的业务表来说,因为它"各自为政"的特性和可能重复的风险,一般不建议直接拿它当主键。但话说回来,regclass类型倒是给咱们提供了一种非常方便的查询和管理数据库元数据的方法。
ROWID呢,是KingbaseES专门提供的一种高效的逻辑行标识符。它单调递增的特性,加上默认就有的唯一索引,让它在需要快速定位和操作单行数据的时候特别有用。当然啦,ROWID和OID在GUC参数配置上谁先谁后的问题,也提醒咱们在配数据库的时候得多留个心眼,别踩了不必要的"坑"。
至于咱们最常用的自增主键(SERIAL/BIGSERIAL),那依然是业务表主键的不二之选。它给咱们的保证最稳定、最可靠,也最符合咱们对业务主键的那种直观理解。
总的来说,把这些行标识符的底层实现、特点和适用范围吃透了,对用KingbaseES的伙计们来说特别重要。这不仅能帮咱们更高效地管理和优化数据库,还能在搞应用设计的时候,根据实际需求选出最合适的行标识策略,从而搭出更结实、跑得更快的数据库应用。在KingbaseES的实践里,把这些技术特性灵活运用起来,可是提升数据库整体效能的关键。