首批通过分布式安全可靠测评,为关键业务系统打造
Oceanbase 数据库 V4.x 版本,对于无主键表分区键默认不参与抽取 Query Range
更新时间:2026-05-14 07:41
在 OceanBase 数据库之前版本中,为了更好兼容 Oracle 堆表的行为,有实现过无主键表,在无主键表内部使用分区键+全局自增列作为隐藏主键,这个做法带来了许多问题:
受制于分区键的长度,RowID 的长度是变长的,Oracle 的 RowID 长度为 10 字节,在很多外部业务应用中,RowID 长度是写死在应用程序中的,很难修改,这导致 OceanBase 的推广遇到了很多问题。
无法进行无主键分区表和无主键非分区表的分区交换,功能上与 Oracle 不兼容。
全局自增列引入了额外的依赖,性能上存在瓶颈,同时也很难做表级备份恢复等操作。 因此在 OceanBase 数据库 V4.0 版本中,重新设计了 OceanBase 数据库的无主键表行为,使用分区内自增列作为隐藏主键,可以取得和 Oracle 行为完全一致的兼容性。 上述改变带来的另外一个变化是对于无主键的分区表,在 OceanBase 数据库 V3.x 版本中分区键是可以参与抽取 Query Range 的,但是在 V4.x 中,分区键不再参与抽取 Query Range。
详细说明
具体示例如下。
在 OceanBase 数据库 V3.x 版本下创建无主键分区表。
CREATE TABLE T ( "DATA_DATE" DATE NOT NULL ENABLE, "BIZ_ID" VARCHAR2(300) NOT NULL ENABLE, "SUBJ_CODE" VARCHAR2(50), "OPEN_ORG_NO" VARCHAR2(50), CONSTRAINT "IND_T_1" UNIQUE ("DATA_DATE", "BIZ_ID") USING INDEX LOCAL ) COMPRESS FOR ARCHIVE REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 partition by list("DATA_DATE") ( partition "D20240430" values (TO_DATE(' 2024-04-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240531" values (TO_DATE(' 2024-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240630" values (TO_DATE(' 2024-06-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240730" values (TO_DATE(' 2024-07-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))); CREATE TABLE "T1" ( "BIZ_ID" VARCHAR2(300) NOT NULL ENABLE, "BIZ_TYPE" VARCHAR2(10) NOT NULL ENABLE, "DATA_DATE" DATE NOT NULL ENABLE ) COMPRESS FOR ARCHIVE REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 partition by list("DATA_DATE") (partition "D20240430" values (TO_DATE(' 2024-04-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240531" values (TO_DATE(' 2024-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240630" values (TO_DATE(' 2024-06-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')), partition "D20240730" values (TO_DATE(' 2024-07-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')));计划中可以看到分区键 DATA_DATE 被加入,同掩藏主键一起参与抽取 Query Range。这样做的好处是减少了基表扫描的数据。

在 OceanBase 数据库 V4.x 版本下创建同样的无主键分区表,但是在 V4.x 版本的计划中,分区键并没有参与抽取 Query Range,只是作为基表扫描后的过滤条件使用。

对于此类问题,可以通过在查询语句中指定分区的方式,缩小分区范围。 也可以在分区键+其他唯一且不为空的字段一起创建唯一索引达到分区剪裁的目的(如果没有唯一不为空的字段,可以添加自增列)。
此外,在此问题中,T 表存在唯一约束 uk ("DATA_DATE", "BIZ_ID") , 但是不能当作唯一主键使用。
主键和唯一约束(唯一索引)的区别。
主键是 not null+ 唯一。 唯一约束(唯一索引)是强调唯一,但是可以为 null。
在上面的例子中,在
DATA_DATE,BIZ_TYPE字段创建 PK 之后,分区键可以参与抽取 Query Range。
适用版本
OceanBase 数据库 V4.x 版本。