首批通过分布式安全可靠测评,为关键业务系统打造
动态分区
更新时间:2026-04-09 14:12:04
核心价值
AP 场景(分析型场景)通常面临以下挑战:
- 海量数据增长: 如日志、用户行为、传感器数据等持续写入。
- 资源管理复杂: 手动创建/删除分区耗时且易出错。
- 存储成本压力: 需自动清理历史数据,避免存储膨胀。
动态分区的解决方案
通过预设规则(如时间单位、预创建周期、过期时间),OceanBase 自动管理分区,实现:
- 零运维扩展: 通过定时任务预创建分区,无需手动干预。(动态分区通过定时任务按预设规则预创建分区;OceanBase 4.4.2/4.5.0 版本的新增 Interval 分区支持数据写入时自动创建分区。)
- 智能清理: 按需删除旧分区,释放存储空间。
- 查询加速: 分区裁剪减少扫描数据量。
功能特性
- 根据
TIME_UNIT(如小时、天、月等)定期创建新分区,确保数据按时间范围自动扩展。 - 分区边界基于时间单位(如
hour、day)划分,适用于按时间序列存储数据的场景(如日志、交易记录)。 - 通过
PRECREATE_TIME指定预创建多长时间的未来分区,避免因数据突增导致的分区不足问题。 - 根据
EXPIRE_TIME定期清理过期分区,释放存储空间。 - 支持自定义时区(
TIME_ZONE),确保跨时区数据的一致性。 - 支持
bigint类型时间戳的精度配置(如BIGINT_PRECISION),适配不同时间精度需求。
关键场景
修改动态分区属性
业务需求变化
- 当需要开启/关闭动态分区管理,可以调整参数 ENABLE 属性。
- 当需保留更长时间数据(如从30天延长到90天),可以调整动态分区
EXPIRE_TIME属性。
业务高峰应对
- 当促销期间,为了避免分区不足,需要预创建更多分区时,可以调整动态分区
PRECREATE_TIME属性。
- 当促销期间,为了避免分区不足,需要预创建更多分区时,可以调整动态分区
修改动态分区的属性示例如下:
-- 修改预创建周期为 3 天,过期时间为 90 天,并开启动态分区
ALTER TABLE user_behavior DYNAMIC_PARTITION_POLICY(
PRECREATE_TIME = '3 DAY',
EXPIRE_TIME = '90 DAY',
ENABLE = TRUE
);
-- 临时关闭动态分区管理
ALTER TABLE user_behavior DYNAMIC_PARTITION_POLICY(ENABLE = FALSE);
动态分区的扩展配置场景
场景:合规要求延长数据保留时间
-- 将过期时间延长至90天 ALTER TABLE user_behavior DYNAMIC_PARTITION_POLICY( EXPIRE_TIME = '90 DAY' );
分区管理
OceanBase 通过内置定时任务进行动态分区管理,且在以下场景支持手动调整:
修改定时任务调度时间,避开业务高峰:
CALL DBMS_SCHEDULER.SET_ATTRIBUTE( 'SCHEDULED_MANAGE_DYNAMIC_PARTITION_DAILY', 'START_DATE', '2025-11-14 02:00:00' );- 假设当前时间为
2025-11-13 15:00:00,默认的下一次调度时间为2025-11-14 00:00:00,希望调整到每天凌晨两点调度,可以将下一次调度时间修改为2025-11-14 02:00:00。
- 假设当前时间为
特殊业务需求:
CALL DBMS_PARTITION.MANAGE_DYNAMIC_PARTITION();- 手动执行一次动态分区管理任务,立即清理过期分区或预创建未来分区(如紧急存储回收)。
动态分区表设计
CREATE TABLE user_behavior (
user_id BIGINT,
event_time DATETIME NOT NULL,
event_type VARCHAR(50),
device_info VARCHAR(255)
)
DYNAMIC_PARTITION_POLICY(
ENABLE = TRUE,
TIME_UNIT = 'hour',
PRECREATE_TIME = '3 hour',
EXPIRE_TIME = '1 DAY',
TIME_ZONE = '+8:00'
)
PARTITION BY RANGE COLUMNS(event_time) (
PARTITION p_start VALUES LESS THAN ('2025-11-13 13:30:00')
);
验证动态分区策略
步骤1:验证表配置
show create table user_behavior\G
输出结果如下:
*************************** 1. row ***************************
Table: user_behavior
Create Table: CREATE TABLE `user_behavior` (
`user_id` bigint(20) DEFAULT NULL,
`event_time` datetime NOT NULL,
`event_type` varchar(50) DEFAULT NULL,
`device_info` varchar(255) DEFAULT NULL
) ORGANIZATION INDEX DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE ENABLE_MACRO_BLOCK_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 DYNAMIC_PARTITION_POLICY = (ENABLE = TRUE, TIME_UNIT = 'HOUR', PRECREATE_TIME = '3HOUR', EXPIRE_TIME = '1DAY', TIME_ZONE = '+8:00', BIGINT_PRECISION = 'NONE')
partition by range columns(`event_time`)
(partition `p_start` values less than ('2025-11-13 13:30:00'))
1 row in set
验证分区:
-- 触发分区扩展,等待系统自动调度,或在测试环境手动执行一次:
CALL DBMS_PARTITION.MANAGE_DYNAMIC_PARTITION();
SHOW CREATE TABLE user_behavior\G
当指定了至少一个分区定义时,预创建分区不会在建表后立刻创建,需等待一次动态分区管理调度,或手动执行一次动态分区管理。在执行动态分区管理时,系统会间隔 time_unit 创建分区,直到最大分区边界超过 now() + precreate_time,创建的第一个分区边界为现存最大分区边界按 time_unit 向上取整。例如,当前时间为 2025-11-13 14:50:00,调度一次动态分区管理后,分区预计结果如下所示:
*************************** 1. row ***************************
Table: user_behavior
Create Table: CREATE TABLE `user_behavior` (
`user_id` bigint(20) DEFAULT NULL,
`event_time` datetime NOT NULL,
`event_type` varchar(50) DEFAULT NULL,
`device_info` varchar(255) DEFAULT NULL
) ORGANIZATION INDEX DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE ENABLE_MACRO_BLOCK_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 DYNAMIC_PARTITION_POLICY = (ENABLE = TRUE, TIME_UNIT = 'HOUR', PRECREATE_TIME = '3HOUR', EXPIRE_TIME = '1DAY', TIME_ZONE = '+8:00', BIGINT_PRECISION = 'NONE')
partition by range columns(`event_time`)
(partition `p_start` values less than ('2025-11-13 13:30:00'),
partition `P2025111313` values less than ('2025-11-13 14:00:00'),
partition `P2025111314` values less than ('2025-11-13 15:00:00'),
partition `P2025111315` values less than ('2025-11-13 16:00:00'),
partition `P2025111316` values less than ('2025-11-13 17:00:00'),
partition `P2025111317` values less than ('2025-11-13 18:00:00'))
1 row in set
若现存最大分区边界小于当前时间,预创建分区会尝试补充历史分区。例如现存最大分区为 PARTITION P0 VALUES LESS THAN ('2025-11-13 11:30:00'),当前时间为 2025-11-13 12:34:56,调度一次动态分区管理后,分区为:
PARTITION P0 VALUES LESS THAN ('2025-11-13 11:30:00'),
PARTITION P2025111311 VALUES LESS THAN ('2025-11-13 12:00:00'),
PARTITION P2025111312 VALUES LESS THAN ('2025-11-13 13:00:00'),
PARTITION P2025111313 VALUES LESS THAN ('2025-11-13 14:00:00'),
PARTITION P2025111314 VALUES LESS THAN ('2025-11-13 15:00:00'),
PARTITION P2025111315 VALUES LESS THAN ('2025-11-13 16:00:00')
步骤2:插入测试数据
-- 插入多类测试数据,覆盖不同时间范围
-- 当前时间假设为 2025-11-13 15:00:00
-- (a) 插入当前小时数据(应落入 P2025111315)
INSERT INTO user_behavior (user_id, event_time, event_type, device_info)
VALUES (1001, '2025-11-13 15:25:00', 'click', 'iPhone15');
-- (b) 插入未来1小时数据(应落入 P2025111316,已预创建)
INSERT INTO user_behavior (user_id, event_time, event_type, device_info)
VALUES (1002, '2025-11-13 16:10:00', 'purchase', 'MacBook');
-- (c) 插入25小时前的过期数据(2025-11-12 13:00:00,落入第一个分区)
INSERT INTO user_behavior (user_id, event_time, event_type, device_info)
VALUES (1003, '2025-11-12 13:00:00', 'old_event', 'Android');
-- (d) 插入刚好在初始分区内的数据(< 13:30)
INSERT INTO user_behavior (user_id, event_time, event_type, device_info)
VALUES (1004, '2025-11-13 13:20:00', 'view', 'iPad');
-- 查看分区扩展
SHOW CREATE TABLE user_behavior\G
输出示例:
*************************** 1. row ***************************
Table: user_behavior
Create Table: CREATE TABLE `user_behavior` (
`user_id` bigint(20) DEFAULT NULL,
`event_time` datetime NOT NULL,
`event_type` varchar(50) DEFAULT NULL,
`device_info` varchar(255) DEFAULT NULL
) ORGANIZATION INDEX DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE ENABLE_MACRO_BLOCK_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 DYNAMIC_PARTITION_POLICY = (ENABLE = TRUE, TIME_UNIT = 'HOUR', PRECREATE_TIME = '3HOUR', EXPIRE_TIME = '1DAY', TIME_ZONE = '+8:00', BIGINT_PRECISION = 'NONE')
partition by range columns(`event_time`)
(partition `p_start` values less than ('2025-11-13 13:30:00'),
partition `P2025111313` values less than ('2025-11-13 14:00:00'),
partition `P2025111314` values less than ('2025-11-13 15:00:00'),
partition `P2025111315` values less than ('2025-11-13 16:00:00'),
partition `P2025111316` values less than ('2025-11-13 17:00:00'),
partition `P2025111317` values less than ('2025-11-13 18:00:00'),
partition `P2025111318` values less than ('2025-11-13 19:00:00'))
1 row in set
步骤3:查询验证
-- 查询最近2小时活跃用户
SELECT
DATE_FORMAT(event_time, '%Y-%m-%d %H:00') AS hour_slot,
COUNT(*) AS event_count,
COUNT(DISTINCT user_id) AS active_users
FROM user_behavior
WHERE event_time >= NOW() - INTERVAL 2 HOUR
GROUP BY hour_slot
ORDER BY hour_slot;
数据结果:
+------------------+-------------+--------------+
| hour_slot | event_count | active_users |
+------------------+-------------+--------------+
| 2025-11-13 13:00 | 1 | 1 |
| 2025-11-13 15:00 | 1 | 1 |
| 2025-11-13 16:00 | 1 | 1 |
+------------------+-------------+--------------+
3 rows in set
步骤4:验证过期数据清理(可选)
等待超过 24 小时,或手动将系统时间模拟推进(测试环境),再次触发管理:
-- 假设现在是 2025-11-14 15:00:00
CALL DBMS_PARTITION.MANAGE_DYNAMIC_PARTITION();
-- 查看分区是否移除了 2025-11-13 14:00 之前的分区
SHOW CREATE TABLE user_behavior\G
步骤 5:监控分区管理任务
输出示例:
SELECT JOB_NAME, ENABLED, NEXT_RUN_DATE
FROM oceanbase.DBA_SCHEDULER_JOBS
WHERE JOB_NAME = 'SCHEDULED_MANAGE_DYNAMIC_PARTITION_HOURLY';
预计输出结果如下:
+-------------------------------------------+---------+----------------------------+
| JOB_NAME | ENABLED | NEXT_RUN_DATE |
+-------------------------------------------+---------+----------------------------+
| SCHEDULED_MANAGE_DYNAMIC_PARTITION_HOURLY | 1 | 2025-11-13 16:00:00.000000 |
+-------------------------------------------+---------+----------------------------+
1 row in set
步骤 6:查看任务执行历史
SELECT
TIMESTAMP,
VALUE1 AS success_tables,
VALUE2 AS failed_tables,
COST_TIME,
RET_CODE
FROM oceanbase.DBA_OB_TENANT_EVENT_HISTORY
WHERE event = 'MANAGE_DYNAMIC_PARTITION'
ORDER BY TIMESTAMP DESC
LIMIT 3;
预计输出结果如下:
+----------------------------+--------------------------+---------------+-----------+----------+
| TIMESTAMP | success_tables | failed_tables | COST_TIME | RET_CODE |
+----------------------------+--------------------------+---------------+-----------+----------+
| 2025-11-13 15:00:00.173069 | [500020, 500053] | [] | 164938 | 0 |
| 2025-11-13 14:47:56.816717 | [500003, 500020, 500053] | [] | 63801 | 0 |
| 2025-11-13 14:00:00.125075 | [500020] | [] | 117113 | 0 |
+----------------------------+--------------------------+---------------+-----------+----------+
3 rows in set
可用于排查分区管理是否成功执行。
步骤 7:验证插入边界行为(可选)
尝试插入超出预创建范围的数据(假设当前时间是 2025-11-13 15:07:00,插入 2025-11-13 20:00:00,预创建上限时间为 2025-11-13 19:00:00):
INSERT INTO user_behavior VALUES (999, '2025-11-13 20:00:00', 'future', 'test');
-- 产生报错:ERROR 1526 (HY000): Table has no partition for value
相关视图
数据字典视图
查询数据字典视图 DBA_OB_DYNAMIC_PARTITION_TABLES 可以查看动态分区表的相关属性。
DBA_OB_DYNAMIC_PARTITION_TABLES视图在所有租户可见,包含当前租户的动态分区表数据。oceanbase.CDB_OB_DYNAMIC_PARTITION_TABLES视图仅在 sys 租户可见,包含所有租户的动态分区表数据。
动态性能视图
查询动态性能视图 V$OB_DYNAMIC_PARTITION_TABLES,从内存中读取动态分区表相关属性,读取性能较好。
- sys 租户下,
V$OB_DYNAMIC_PARTITION_TABLES展示所有租户的动态分区表数据。 - 用户租户下,仅展示当前租户的动态分区表数据。