oceanbase表分区指定

OceanBase 分区表指定

一、分区表的基本概念

以按月分区的订单表为例,应用看到的是一张逻辑表 orders

text 复制代码
应用看到的一张逻辑表:orders
                    │
         ┌──────────┼──────────┐
         ↓          ↓          ↓
     1 月分区    2 月分区    3 月分区
     存 1 月数据  存 2 月数据  存 3 月数据

应用始终使用同一个表名进行查询:

sql 复制代码
SELECT *
FROM orders
WHERE created_at >= '2026-02-01'
  AND created_at <  '2026-03-01';

数据库根据查询条件判断只需要访问 2 月分区,这个过程称为分区裁剪(Partition Pruning)。

严格来说,不宜把每个分区简单称为"一张物理表":分区是同一张表的数据组成部分,不是应用需要分别操作的独立业务表。在 OceanBase 中,分区可以分布到不同的 OBServer,并按照配置维护多个副本。

可以这样理解:

概念 含义
应用访问的完整数据集合
分区 将表中的数据按规则拆成不同部分
副本 为同一部分数据保存多份冗余

分区是"拆开存",副本是"复制存"。

二、建表时指定分区

在 OceanBase MySQL 兼容模式下,建表时在 CREATE TABLE 语句后增加 PARTITION BY,即可指定分区规则。

建议使用 orders 作为表名,因为 ORDER 是 SQL 关键字。如果必须使用 order,需要用反引号包裹:order

分区键应根据主要查询条件和数据管理方式选择。下面给出两种常见方案,通常需要结合业务场景二选一。

方案一:按订单 ID 使用 HASH 分区

如果主要按订单 ID 查询,并且希望将数据均匀分散到多个分区,可以使用 HASH 分区:

sql 复制代码
CREATE TABLE orders (
    id BIGINT NOT NULL AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    status TINYINT NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

    PRIMARY KEY (id),
    KEY idx_user_created (user_id, created_at)
)
PARTITION BY HASH (id)
PARTITIONS 8;

关键部分如下:

sql 复制代码
PARTITION BY HASH (id)  -- 使用 id 作为分区键
PARTITIONS 8            -- 建立 8 个分区

这里的 8 只是示例,不代表所有场景都应该使用 8 个分区。分区数量应结合预计数据量、租户资源和访问模式确定,也不需要等于 Zone 数量。

插入和查询

应用不需要指定分区,数据库会根据分区规则决定数据落在哪个分区:

sql 复制代码
INSERT INTO orders (user_id, amount)
VALUES (1001, 99.90);

按 ID 查询时,数据库可以根据 ID 定位对应分区:

sql 复制代码
SELECT *
FROM orders
WHERE id = 12345;

不同查询条件对 HASH 分区裁剪的影响如下:

查询条件 对该分区设计的影响
id = 12345 可以定位对应分区
id IN (12345, 12346) 可以定位这些 ID 对应的分区
user_id = 1001 不能仅凭该条件裁剪 ID 分区;即使使用局部索引,也可能涉及多个分区
id > 12345 HASH 分区不按 ID 连续范围排列,通常仍需访问多个分区
按时间范围查询 不能仅凭时间条件裁剪 ID 分区

因此,HASH 分区有助于分散数据和访问压力,但不意味着所有查询都会更快。

方案二:按时间使用 RANGE 分区

如果主要按月份查询、归档和清理历史订单,可以使用 RANGE 分区:

sql 复制代码
CREATE TABLE orders (
    id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    amount DECIMAL(18, 2) NOT NULL,
    status TINYINT NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL,

    PRIMARY KEY (created_at, id)
)
PARTITION BY RANGE COLUMNS (created_at) (
    PARTITION p_before_202609
        VALUES LESS THAN ('2026-09-01'),

    PARTITION p202609
        VALUES LESS THAN ('2026-10-01'),

    PARTITION p202610
        VALUES LESS THAN ('2026-11-01'),

    PARTITION p_future
        VALUES LESS THAN (MAXVALUE)
);

对应的时间范围如下:

分区 时间范围
p_before_202609 2026-09-01 之前
p202609 2026-09-01 至 2026-10-01,不含结束时刻
p202610 2026-10-01 至 2026-11-01,不含结束时刻
p_future 2026-11-01 及以后

按时间范围查询时,可以裁剪到对应分区:

sql 复制代码
SELECT *
FROM orders
WHERE created_at >= '2026-09-01'
  AND created_at <  '2026-10-01';
该方案的注意事项
  • PRIMARY KEY (created_at, id) 只保证组合唯一,不单独保证 id 全表唯一。如果需要数据库强制保证 ID 全局唯一,应结合目标 OceanBase 版本和索引类型设计全局唯一索引。
  • 需要定期维护后续时间分区,例如在新月份到来前新增分区。
  • 当前写入通常会集中在最新分区,需要结合业务写入量评估热点问题。
  • 分区键出现在主键中,是为了满足分区表主键设计约束;实际建表前仍应确认目标 OceanBase 版本的语法和限制。

三、应用如何访问分区表

应用通常只访问逻辑表名,不需要直接操作分区名:

sql 复制代码
INSERT INTO orders (id, user_id, amount, status, created_at)
VALUES (1000001, 1001, 99.90, 0, '2026-09-15 10:30:00');

SELECT *
FROM orders
WHERE created_at >= '2026-09-01'
  AND created_at <  '2026-10-01';

数据库会根据插入数据的分区键进行路由,并根据查询条件执行分区裁剪。

为了让分区裁剪更容易生效,时间范围查询建议使用左闭右开形式:

sql 复制代码
created_at >= '开始时间'
AND created_at <  '结束时间'

例如按月查询时使用"当月第一天(含)到下月第一天(不含)",避免使用依赖时间精度的 23:59:59

四、如何确认建表结果

查看完整建表语句:

sql 复制代码
SHOW CREATE TABLE orders;

也可以查询分区元数据:

sql 复制代码
SELECT
    TABLE_NAME,
    PARTITION_NAME,
    PARTITION_METHOD,
    PARTITION_EXPRESSION,
    PARTITION_DESCRIPTION,
    TABLE_ROWS
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = 'orders'
ORDER BY PARTITION_ORDINAL_POSITION;

五、分区与副本的职责边界

分区规则决定的是"哪些数据放在一起",例如:

  • HASH 分区按照分区键的哈希值分散数据。
  • RANGE 分区按照键值范围组织数据。

分区规则不直接指定数据放到哪个 Zone。分区在 OBServer 上的分布,以及副本的放置和数量,由 OceanBase 结合租户资源、Zone 布局、复制策略和调度机制进行管理。

六、选型建议

主要需求 优先考虑
按订单 ID 点查,关注数据和访问压力的均匀分布 HASH 分区
按月份查询、归档、删除历史数据 RANGE 分区
同时强依赖订单 ID 点查和时间范围查询 结合实际访问比例评估分区键、索引和二级分区方案

正式建表前,建议确认以下信息:

  1. OceanBase 的具体版本和 MySQL 兼容模式限制。
  2. 最主要的查询条件,以及是否需要按时间批量归档或删除。
  3. 预计数据量、写入峰值和数据增长速度。
  4. 是否要求 id 全表唯一,以及是否需要全局唯一索引。
  5. 租户的 Zone 数量、资源规格和副本布局要求。
相关推荐
喂自己代言1 天前
从 0.7 秒到 11 毫秒:OceanBase 一条慢 SQL 的三连坑优化实战
数据库·sql·oceanbase
marvelyu3 天前
OceanBase 调优实战:从慢查询到高并发的系统性优化
oceanbase
2601_962071579 天前
基于DataX迁移MySQL到OceanBase集群
数据库·mysql·oceanbase
光锥智能11 天前
OceanBase领跑数字政府数据库选型:产品能力、市场潜力、技术潜力均居首
数据库·人工智能·oceanbase
数智前线12 天前
服务22个省数字政府建设,OceanBase领跑数字政府数据库选型
oceanbase
云贝贝贝12 天前
OceanBase 生产运维 7 个高频现场:从连不上到误删兜底
运维·ffmpeg·oceanbase
灰原喜欢柯南15 天前
OceanBase 常用命令入门
oceanbase
OceanBase数据库官方博客15 天前
OceanBase:从核心系统现代化到AI 创新
人工智能·oceanbase
spencer_tseng16 天前
[OceanBase-Desktop-Setup-1.0.0.exe] CPU virtualization is not enabled
oceanbase·cpu·virtualization