官方文档有这样的描述:
意思是分区间如果是null的情况,会把此条记录写入 values less than (MAXVALUE)) 这个分区吗?
实际案例:
obclient [test]> show create table parttb_range_2 \G
*************************** 1. row ***************************
Table: parttb_range_2
Create Table: CREATE TABLE `parttb_range_2` (
`id` int(11) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`info` varchar(20) DEFAULT NULL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
partition by range columns(gmt_create)
(partition `p0` values less than ('2025-01-01 00:00:00'),
partition `p1` values less than (MAXVALUE))
1 row in set (0.004 sec)
obclient [test]> select * from parttb_range_2;
+------+---------------------+------+
| id | gmt_create | info |
+------+---------------------+------+
| 2 | 2024-12-01 00:00:00 | 2 |
| 3 | NULL | 3 |
| 1 | 2025-01-01 00:00:00 | 1 |
+------+---------------------+------+
3 rows in set (0.053 sec)
explain route select * from parttb_range_2 where gmt_create is null;
实际上好像路由到P0分区了
1 个赞
论坛小助手
#4
根据文档库中的信息,RANGE
分区在处理 NULL
值时的行为如下:
-
官方文档描述:
在 OceanBase 数据库中,默认采用 NULL first
的比较模式。这意味着在排序或分区时,NULL
值会被视为小于任何非 NULL
值。因此,在 RANGE
分区表中,NULL
值会路由到第一个分区(即定义为 VALUES LESS THAN (某个值)
的分区)。
-
实际案例分析:
根据您提供的表结构和查询结果:
CREATE TABLE `parttb_range_2` (
`id` int(11) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`info` varchar(20) DEFAULT NULL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
partition by range columns(gmt_create)
(partition `p0` values less than ('2025-01-01 00:00:00'),
partition `p1` values less than (MAXVALUE));
- 表的分区规则是基于
gmt_create
列的 RANGE COLUMNS
分区。
- 第一个分区
p0
定义为 VALUES LESS THAN ('2025-01-01 00:00:00')
。
- 第二个分区
p1
定义为 VALUES LESS THAN (MAXVALUE)
。
当插入一条记录的 gmt_create
列为 NULL
时,根据 NULL first
的比较规则,NULL
值会被视为小于 '2025-01-01 00:00:00'
,因此该记录被路由到 p0
分区。
-
解释您的疑问:
您提到的“是否会把此条记录写入 VALUES LESS THAN (MAXVALUE)
这个分区”实际上不会发生。因为 NULL
值在 RANGE
分区中被视为小于任何具体的值(如 '2025-01-01 00:00:00'
),所以它会被路由到第一个匹配的分区 p0
,而不是 p1
。
-
验证查询计划:
您通过 EXPLAIN ROUTE
查询发现记录确实路由到了 p0
分区,这与上述逻辑一致。
总结
根据文档库中的信息以及实际案例分析,RANGE
分区表中 NULL
值会被路由到第一个匹配的分区(即 VALUES LESS THAN (某个值)
的分区)。在您的例子中,NULL
值被正确路由到了 p0
分区,而不是 p1
分区。
如果您希望避免这种行为,可以在设计表时明确排除 NULL
值,或者使用 NVL()
或 IFNULL()
函数将 NULL
转换为特定值。例如:
CREATE TABLE `parttb_range_2` (
`id` int(11) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`info` varchar(20) DEFAULT NULL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
partition by range columns(NVL(gmt_create, '9999-12-31 23:59:59'))
(partition `p0` values less than ('2025-01-01 00:00:00'),
partition `p1` values less than (MAXVALUE));
这样可以确保 NULL
值被路由到指定的分区。
具体信息可参考以下文档:
- 向量检索核心功能
- 0001 ~ 3999
- 使用 OceanBase 数据库分区表进行水平拆分
- SQL FAQ
- information_schema.role_column_grants
- 5000 ~ 5999
- OceanBase 术语
- 查询中使用 NULL 相关函数
1 个赞
辞霜
#5
官网并未说存放在哪个分区,根据自己测试的为基准
你看的是oracle模式的,建议咨询商业技术支持
1 个赞