在处理海量数据(如车辆定位、订单记录等)时,单表数据量突破千万后,查询和维护会变得极其困难。本文总结了基于 Range 分区 的全生命周期管理方案,涵盖了从建表优化到高效清理的核心操作。
1. 建立分区表 (核心设计)
在建表时,最关键的是主键必须包含分区字段。针对不同的时间字段类型,有两种标准的建表方式:
A. 针对 DATETIME 类型 (推荐使用 TO_DAYS)
适用于公交定位等数据,兼容性最强。
CREATE TABLE `positioning_data` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`cph` varchar(20) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 自动记录入库时间
PRIMARY KEY (`id`, `created_at`) -- 必须包含分区字段
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (TO_DAYS(`created_at`)) (
PARTITION p20251227 VALUES LESS THAN (TO_DAYS('2025-12-28')),
PARTITION p20251228 VALUES LESS THAN (TO_DAYS('2025-12-29')),
PARTITION p_future VALUES LESS THAN MAXVALUE -- 兜底分区,防止溢出
);
B. 针对 TIMESTAMP 类型 (推荐使用 UNIX_TIMESTAMP)
适用于订单、日志等表。
CREATE TABLE `order_cancel` (
`id` bigint NOT NULL AUTO_INCREMENT,
`received_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`, `received_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
PARTITION BY RANGE (UNIX_TIMESTAMP(`received_at`)) (
PARTITION p20251227 VALUES LESS THAN (UNIX_TIMESTAMP('2025-12-28 00:00:00')),
PARTITION p20251228 VALUES LESS THAN (UNIX_TIMESTAMP('2025-12-29 00:00:00')),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
2. 查看分区状态
执行分区后,我们需要实时监控各个“抽屉”里的数据量和物理占用。
-- 查看指定表的分区分布、行数及物理大小
SELECT
PARTITION_NAME AS '分区名',
PARTITION_DESCRIPTION AS '分区范围值',
TABLE_ROWS AS '预估行数',
ROUND(DATA_LENGTH / 1024 / 1024, 2) AS '数据大小(MB)',
ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS '索引大小(MB)'
FROM information_schema.PARTITIONS
WHERE TABLE_NAME = 'positioning_data'
AND TABLE_SCHEMA = 'cleaned_data';
3. 分区数据的精准清理
这是分区表最大的优势:秒级清理,不锁全表,不占 Undo Log。
A. 清空分区数据 (保留结构)
如果你想清理某一天的数据,但希望保留分区以便新数据继续进入。
ALTER TABLE positioning_data TRUNCATE PARTITION p20251227;
B. 物理删除分区 (连同结构)
如果你确定某天的数据永远不再需要,可以直接丢弃。
ALTER TABLE positioning_data DROP PARTITION p20251227;
4. 全局数据统计
当数据库中存在多个千万级大表时,可以使用子查询快速横向对比。
SELECT
(SELECT COUNT(*) FROM tsms_position_vehicle) AS tsms_position_vehicle_count,
(SELECT COUNT(*) FROM positioning_data) AS positioning_data_count,
(SELECT COUNT(*) FROM order_cancel) AS order_cancel_count;
5. 彻底重置表 (Truncate Table)
如果需要清空整个表(包括所有分区数据)并重置自增 ID,TRUNCATE 比 DROP 更轻量。
TRUNCATE TABLE positioning_data;
TRUNCATE TABLE order_cancel;
6. 避坑指南与经验总结
- 主键限制:MySQL 要求分区字段必须是主键的一部分,否则无法创建分区。
- 锁竞争问题:如果在删除表(DROP)时遇到
Unknown table或一直卡住,通常是因为后台有类似 Hadoop 的采集程序正在进行高频写入,产生了元数据锁(Metadata Lock)。操作前应先停掉写入源。 - 自动计时:使用
DEFAULT CURRENT_TIMESTAMP字段作为分区依据,可以实现数据入库时自动归位,无需修改业务代码。 - 粒度选择:对于千万级数据,建议按“天”分区;对于亿级数据,才考虑按“小时”分区。分区过多会增加元数据管理的开销。
本文基于 2025 年 12 月车联网大数据处理实战经验整理。

