【OceanBase 诊断调优】—— 无主键表的 ROWID 和隐藏主键 __pk_increment
适用版本:V2.1.x、V2.2.x、V3.1.x、V3.2.x、V4.x
无主键表是指用户在创建时没有指定主键的表,此时 OceanBase MySQL 模式和 Oracle 模式的数据库均会采用一个自增的列作为隐藏主键。隐藏主键的数据类型为 BIGINT,最大值为 2^64 。
对于 OceanBase Oracle 模式的数据库,跟原生 Oracle 对齐,每个表都有一个名为 ROWID 的伪列。OceanBase Oracle 数据库使用 ROWID 数据类型来存储数据库中每一行的地址。本文主要介绍 OceanBase 各个版本中这两个对象的特点、二者之间的关系,以及如何使用 select 语句来查询 ROWID 和隐藏主键。
详细说明
ROWID
在 OceanBase Oracle 数据库中,每个表都有一个名为 ROWID 的伪列。 伪列的行为类似一个表的普通列,但实际上并没有存储在表中。可以通过伪列执行 SELECT 操作,但不能对它们的值执行 INSERT、UPDATE、DELETE 操作。伪列也类似于没有参数的 SQL 函数。不带参数的函数通常为结果集中的每一行返回相同的值,而伪列通常为每一行返回不同的值。 ROWID 伪列的值是每行数据的 Key(对于有主键表是 Primary Key,对于无主键表是系统自动生成的序列),通过 Base64 编码转换而成。可以通过使用保留字 ROWID 作为列名的 SQL 来访问每一行的 ROWID。 在 OceanBase 数据库 V2.x/V3.x 版本中无主键表的 ROWID 会编码分区键的信息(OceanBase 数据库 V2.x/V3.x 版本中无主键表的 ROWID 是按照 自增列+分区键 编码转换的),长度不固定。如果分区键字段内容很长的话,ROWID 就会很长;而在 OceanBase 数据库 V4.x 版本中无主键表的 ROWID 为固定长度 16 字节,彻底解决了 ROWID 超长问题。
隐藏主键
OceanBase 数据库的无主键表采用自增列作为隐藏主键。无主键表利用了自增列的多分区全局唯一的原则,以此保证无主键表隐藏键的唯一性。
-
ROWID 长度调整前(OceanBase 数据库 V2.x/V3.x 版本)。
无主键表隐藏主键的格式如下:
create table t1(c1 int); -- 隐藏主键为__pk_increment
create table t1(c1 int, c2 int) partition by hash(c2); -- 隐藏主键为(c2, __pk_increment)
可以看出无主键表的隐藏主键里面会包含分区键,这使得 OceanBase 的无主键表 ROWID 的长度是不固定的,最长可能会到 16K 。
-
ROWID长度调整后(OceanBase 数据库 V4.x 版本)。
无主键表的隐藏主键格式变为如下:
create table t1(c1 int); -- 隐藏主键为__pk_increment
create table t1(c1 int, c2 int) partition by hash(c2); -- 隐藏主键为(__pk_increment)
可以看出在 OceanBase 数据库 V4.x 版本中无主键分区表自动创建的隐藏主键不再包含分区键了。
二者关系及如何查看
OceanBase 数据库 Oracle 模式中的 ROWID 是基于 __pk_increment
和其它信息(OceanBase 数据库 V2.x/3.x 版本中为分区键,V4.x 版本中为 tablet id)一起编码产生的一个伪列,但不等同于 __pk_increment
。
示例如下:
-
查看表 t2 的表结构。
obclient [SYS]> desc t2;
输出结果如下:
+-------+---------------+------+------+---------+-------+ | FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | +-------+---------------+------+------+---------+-------+ | ID | NUMBER(38) | YES | UNI | NULL | NULL | | NAME | VARCHAR2(100) | YES | NULL | NULL | NULL | +-------+---------------+------+------+---------+-------+ 2 rows in set (0.004 sec)
-
查询表 t2 的完整结构。
obclient [SYS]> show create table t2;
输出结果如下:
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | TABLE | CREATE TABLE | +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | T2 | CREATE TABLE "T2" ( "ID" NUMBER(*,0), "NAME" VARCHAR2(100), UNIQUE ("ID") ) COMPRESS FOR ARCHIVE REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 | +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.005 sec)
-
查询表 t2 的内容。
obclient [SYS]> select * from t2;
输出结果如下:
+------+------+ | ID | NAME | +------+------+ | 1 | a | | 2 | b | | NULL | c | +------+------+ 3 rows in set (0.001 sec)
-
在查询表 t2 语句中添加 hint 打开隐藏列可见,获取
__pk_increment
值。obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment" from t2; -- OceanBase 数据库 V4.x 版本中 Oracle 模式和 MySQL 模式均适用
输出结果如下:
+------+----------------+ | ID | __pk_increment | +------+----------------+ | 1 | 1 | | 2 | 4 | | NULL | 6 | +------+----------------+ 3 rows in set (0.001 sec)
-
在查询表 t1 语句中添加 hint 打开隐藏列可见,获取
__pk_increment
值。MySQL [test]> select /*+ opt_param('hidden_column_visible','true') */ id,`__pk_increment` from t1; +------+----------------+ | id | __pk_increment | +------+----------------+ | 1 | 1 | | 2 | 2 | | NULL | 3 | +------+----------------+ 3 rows in set (0.001 sec) MySQL [test]> select /*+ opt_param('hidden_column_visible','true') */ id,__pk_increment from t1; +------+----------------+ | id | __pk_increment | +------+----------------+ | 1 | 1 | | 2 | 2 | | NULL | 3 | +------+----------------+ 3 rows in set (0.003 sec)
-
在查询表 t2 语句中添加 hint 打开隐藏列可见,获取
__pk_increment
和ROWID
值。obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment",rowid from t2;
输出结果如下:
+------+----------------+------------------+ | ID | __pk_increment | ROWID | +------+----------------+------------------+ | 1 | 1 | gAADDVQAAAAAAQ== | | 2 | 4 | gAADDVQAAAAABA== | | NULL | 6 | gAADDVQAAAAABg== | +------+----------------+------------------+ 3 rows in set (0.003 sec)
-
在查询表 t2 语句中添加 hint 打开隐藏列可见,获取
__pk_increment
值和ROWID
的长度值。obclient [SYS]> select /*+ opt_param('hidden_column_visible','true') */ id,"__pk_increment",length(rowid) from t2;
输出结果如下:
+------+----------------+---------------+ | ID | __pk_increment | LENGTH(ROWID) | +------+----------------+---------------+ | 1 | 1 | 16 | | 2 | 4 | 16 | | NULL | 6 | 16 | +------+----------------+---------------+ 3 rows in set (0.001 sec)
总结
-
hidden_column_visible
的 sql hint 是在 OceanBase 数据库 V4.x 版本中才引入的,而在 V3.x 版本中无此 hint,因此在 OceanBase 数据库 V3.x 版本中 Oracle 模式下目前暂不支持直接查询隐藏主键__pk_increment
。 -
对于 OceanBase 数据库 V2.x/V3.x/V4.x MySQL 模式租户,还可以使用内部用户
__oceanbase_inner_drc_user
去查询隐藏主键,具体参见:OceanBase 数据库中如何访问隐藏自增列的值
原文地址:https://blog.csdn.net/weixin_40449300/article/details/144028590
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!