数据分区与分表
引用文件
本文引用的文件
- docs/test/tdengine.md
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeCountDayMapper.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeDetailMapper.java
- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/MysqlPartitionException.java
目录
简介
本设计文档围绕海量数据的分区与分表展开,重点覆盖:
- 海量时间序列数据的分区策略:按时间分区、按业务域分表的设计思路与落地实践
- TDengine 时序数据库在设备心跳、运行日志、活动统计等场景的应用与优化
- MySQL 分表策略:水平分表与垂直分表的选择原则与实现
- 数据迁移方案与分表后的查询优化策略
- 数据一致性保证、分表键选择、扩容策略等关键技术点
- 不同数据类型的分区最佳实践与性能对比
项目结构
本仓库中与分区与分表相关的关键模块与文件分布如下:
- TDengine 场景与归档策略:位于 docs/test/tdengine.md
- MySQL 分表与分区工具:位于 yudao-module-rule/util/MacPartitionUtil.java 与对应的 SQL 分区定义
- 活动日志按日期分表与统计:位于 yudao-module-task/job/AppActivityJob.java
- TDengine 设备运行统计与归档重构:位于 yudao-module-device/job/DeviceRuntimeCountJob.java 与相关 Mapper
- TDengine 数据对象与标签设计:位于 yudao-module-system/dal/dataobject/visit/VisitMinuteDO.java
图表来源
- docs/test/tdengine.md
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeCountDayMapper.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeDetailMapper.java
章节来源
- docs/test/tdengine.md
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeCountDayMapper.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeDetailMapper.java
核心组件
- MySQL 分区工具与表结构
- MacPartitionUtil:提供按父表ID与MAC地址的复合分区号计算,支持高两位与低两位分区组合,以及按MAC或ID获取所有分区号集合
- rule_mac_item 与 rule_mac_resource_item:均采用 LIST 分区,分区键为 partition_index,分区数量覆盖 1010~1939 的组合
- 活动日志按日期分表
- AppActivityJob:按日期创建/维护分表,表名包含日期后缀;同时按 partition_index 进行 LIST 分区
- TDengine 分区与归档
- VisitMinuteDO:定义超级表与子表命名规则、标签字段 month 与 data_key,便于按时间与业务域分表
- DeviceRuntimeCountJob:负责 TDengine 数据库的影子库创建、数据源切换、旧库导出与重置,实现“热数据乱序写入 → 定期 ETL 清洗 → 归档数据有序重写”
- DeviceRuntimeCountDayMapper 与 DeviceRuntimeDetailMapper:支持动态表名查询与明细查询
章节来源
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeCountDayMapper.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/dal/tdengine/deviceRuntime/DeviceRuntimeDetailMapper.java
架构总览
下图展示 TDengine 与 MySQL 在海量数据场景下的分区与分表架构,以及归档与查询路径。
图表来源
- docs/test/tdengine.md
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
详细组件分析
TDengine 时序分区与归档
- 设计要点
- 超级表与子表:VisitMinuteDO 定义了超级表与子表命名规则,子表按业务域(url、serverIp、domain、port)与月份(month)组合命名,标签字段用于高效过滤与聚合
- 时间粒度:子表 ts 字段按分钟取整,确保时间有序性,有利于列式压缩与索引
- 归档策略:DeviceRuntimeCountJob 通过“影子库 + 数据源切换 + taosdump 导出 + 有序重写”实现热数据到归档库的迁移,恢复列式压缩优势
- 乱序写入风险
- 文档指出:在相同数据量下,有序写入磁盘占用约为乱序写入的 1/5;乱序写入会导致压缩比从约 5% 恶化到 30%+,极端情况下压缩比超过 100%
- 最佳实践
- 业务层缓存与排序:对延迟到达的数据先按时间排序,再批量写入
- 消息队列与流处理:通过 MQ/Flink 在消费端维持时间有序
- TDengine 配置:合理设置乱序容忍窗口,定期执行数据整理与压缩优化
图表来源
- docs/test/tdengine.md
- docs/test/tdengine.md
- docs/test/tdengine.md
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
章节来源
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- docs/test/tdengine.md
MySQL 分表策略与分区工具
- 水平分表
- 活动日志按日期分表:AppActivityJob 按日期创建/维护分表,并在表上按 partition_index 进行 LIST 分区,分区数量覆盖 0~149
- 规则关联表按业务域与 MAC 分区:MacPartitionUtil 提供按父表 ID 与 MAC 的高两位/低两位分区号计算,最终分区号为 1010~1939 的组合
- 垂直分表
- 通过将宽表拆分为多个窄表,按字段访问热点与生命周期分离,降低单表宽度与 IO 压力
- 分表键选择
- 活动日志:partition_index 作为分区键,来源于业务域与时间维度的组合
- 规则关联表:partition_index 作为分区键,来源于父表 ID 与 MAC 的哈希组合
- 查询优化
- 明确分区键参与查询条件,避免全表扫描
- 使用分区裁剪:WHERE 条件命中具体分区,减少扫描范围
- 定期维护:重建分区统计信息,保持查询计划最优
图表来源
章节来源
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
数据迁移方案与查询优化
- 迁移方案
- TDengine:通过 XXL-Job 调度,使用 taosdump 导出热表数据,Python 脚本按天有序批量重写入归档库,实现“热数据乱序写入 → 定期 ETL 清洗 → 归档数据有序重写”
- MySQL:按日期滚动创建分表,配合 LIST 分区键 partition_index,实现按业务域与时间维度的快速裁剪
- 查询优化
- 明确分区键参与过滤条件,避免跨分区扫描
- 对高频查询字段建立合适索引,结合分区裁剪提升性能
- 对超大表采用分区裁剪 + 二级索引 + 读写分离策略
图表来源
- docs/test/tdengine.md
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
章节来源
- docs/test/tdengine.md
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
数据一致性与扩容策略
- 一致性
- TDengine:通过“有序写入 + 归档重写”恢复压缩与索引优势,降低碎片与小块,提升整体一致性
- MySQL:通过分区键与分区裁剪,确保写入与查询命中目标分区,减少跨分区事务复杂度
- 扩容策略
- TDengine:按业务域与时间维度扩展超级表子表,归档库按月/季度滚动,结合 taosdump 与有序重写实现平滑扩容
- MySQL:按日期滚动分表 + LIST 分区,新增分区键组合以承载新增业务域或时间窗口
章节来源
- docs/test/tdengine.md
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
依赖关系分析
- 组件耦合
- AppActivityJob 依赖 JdbcTemplate 与业务服务,负责按日期创建/维护分表与分区
- MacPartitionUtil 为规则关联表提供分区号计算,SQL 分区表定义与之对应
- DeviceRuntimeCountJob 依赖远程 SSH 与 taosdump,负责 TDengine 数据库的影子库创建与数据迁移
- VisitMinuteDO 为 TDengine 超级表与子表命名与标签提供依据
- 外部依赖
- TDengine:taosdump、SSH 远程执行
- XXL-Job:调度与任务编排
- MySQL:InnoDB 分区与索引
图表来源
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
章节来源
- yudao-module-task/yudao-module-task-biz/src/main/java/cn/iocoder/yudao/module/task/job/AppActivityJob.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
- sql/mysql/rule/rule_mac_item.sql
- sql/mysql/rule/rule_mac_resource_item.sql
- yudao-module-device/yudao-module-device-biz/src/main/java/cn/iocoder/yudao/module/device/job/DeviceRuntimeCountJob.java
- yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/visit/VisitMinuteDO.java
性能考量
- TDengine
- 有序写入显著提升压缩比与查询性能;乱序写入导致索引与块管理开销增大,压缩比恶化
- 通过归档重写恢复列式压缩与索引优势,降低磁盘占用与查询延迟
- MySQL
- LIST 分区 + 分区键裁剪可显著减少扫描范围;建议对高频查询字段建立合适索引
- 按日期滚动分表可实现热点数据与历史数据分离,提升写入与查询效率
[本节为通用性能讨论,无需特定文件引用]
故障排查指南
- MySQL 分区异常
- 当分区号不符合规范(如低两位不在 10~99)时,MacPartitionUtil 抛出 MysqlPartitionException,需检查父表 ID 或 MAC 的哈希计算
- TDengine 写入异常
- 若发现压缩比异常升高或磁盘占用激增,应检查写入顺序与时间戳,必要时触发归档任务进行有序重写
- 数据迁移失败
- 检查 SSH 连接与 taosdump 命令执行权限,确认远程主机可达与认证配置正确
章节来源
- yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/MysqlPartitionException.java
- yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/util/MacPartitionUtil.java
结论
- TDengine 在时间序列场景下对写入顺序极为敏感,有序写入可获得极高压缩比与良好查询性能;通过归档与有序重写可恢复压缩优势
- MySQL 通过 LIST 分区与分区键裁剪,结合按日期滚动分表,可有效支撑海量数据的写入与查询
- 分区键选择与业务域设计密切相关,需兼顾写入热点、查询模式与未来扩容需求
- 建议在应用层与系统层协同治理乱序写入,确保分区分表策略发挥最大价值
[本节为总结性内容,无需特定文件引用]
附录
- TDengine 乱序写入与归档策略参考:见 docs/test/tdengine.md
- MySQL 分区表定义参考:rule_mac_item.sql、rule_mac_resource_item.sql
- 分区工具与计算逻辑:MacPartitionUtil.java
- 活动日志分表与统计:AppActivityJob.java
- TDengine 超级表与子表命名:VisitMinuteDO.java
- TDengine 数据库重构与归档:DeviceRuntimeCountJob.java
[本节为补充说明,无需特定文件引用]