跳到主要内容

数据分区与分表

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本设计文档围绕海量数据的分区与分表展开,重点覆盖:

  • 海量时间序列数据的分区策略:按时间分区、按业务域分表的设计思路与落地实践
  • 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

Mermaid Diagram Code:

graph TB
subgraph "文档与策略"
TD["TDengine 乱序写入与归档策略<br/>docs/test/tdengine.md"]
end
subgraph "MySQL 分表"
Util["Mac 分区工具类<br/>MacPartitionUtil.java"]
SQL1["rule_mac_item 分区表定义<br/>rule_mac_item.sql"]
SQL2["rule_mac_resource_item 分区表定义<br/>rule_mac_resource_item.sql"]
end
subgraph "活动日志分表"
Job["AppActivityJob<br/>按日期创建/维护分表"]
end
subgraph "TDengine 分表与归档"
VDO["VisitMinuteDO<br/>超级表子表命名与标签"]
DRJ["DeviceRuntimeCountJob<br/>数据库重构与归档"]
DRC["DeviceRuntimeCountDayMapper<br/>动态表查询"]
DRD["DeviceRuntimeDetailMapper<br/>明细查询"]
end
TD --> DRJ
Util --> SQL1
Util --> SQL2
Job --> SQL1
VDO --> DRJ
DRJ --> DRC
DRJ --> DRD

图表来源

章节来源

核心组件

  • 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:支持动态表名查询与明细查询

章节来源

架构总览

下图展示 TDengine 与 MySQL 在海量数据场景下的分区与分表架构,以及归档与查询路径。

Mermaid Diagram Code:

graph TB
Dev["设备/终端"] --> SDK["上报 SDK/HTTP"]
SDK --> Svc["业务服务"]
Svc --> |写入| TDE[(TDengine 热表)]
Svc --> |写入| MYSQL[(MySQL 热表)]
subgraph "TDengine 热/归档"
TDE
STBL["超级表<br/>VisitMinuteDO"]
SUB1["子表:按业务域+月份<br/>按分钟粒度"]
TDE --> STBL --> SUB1
STBL --> |归档| TA["XXL-Job 归档任务"]
TA --> |导出/压缩/有序重写| ARCHIVE["TDengine 归档库"]
end
subgraph "MySQL 热/分表"
MYSQL
P1["rule_mac_item 分区表<br/>LIST(partition_index)"]
P2["rule_mac_resource_item 分区表"]
ACT["AppActivityJob 按日期分表"]
end
Svc --> |查询| TDE
Svc --> |查询| MYSQL

图表来源

详细组件分析

TDengine 时序分区与归档

  • 设计要点
    • 超级表与子表:VisitMinuteDO 定义了超级表与子表命名规则,子表按业务域(url、serverIp、domain、port)与月份(month)组合命名,标签字段用于高效过滤与聚合
    • 时间粒度:子表 ts 字段按分钟取整,确保时间有序性,有利于列式压缩与索引
    • 归档策略:DeviceRuntimeCountJob 通过“影子库 + 数据源切换 + taosdump 导出 + 有序重写”实现热数据到归档库的迁移,恢复列式压缩优势
  • 乱序写入风险
    • 文档指出:在相同数据量下,有序写入磁盘占用约为乱序写入的 1/5;乱序写入会导致压缩比从约 5% 恶化到 30%+,极端情况下压缩比超过 100%
  • 最佳实践
    • 业务层缓存与排序:对延迟到达的数据先按时间排序,再批量写入
    • 消息队列与流处理:通过 MQ/Flink 在消费端维持时间有序
    • TDengine 配置:合理设置乱序容忍窗口,定期执行数据整理与压缩优化

Mermaid Diagram Code:

flowchart TD
Start(["开始:热表数据"]) --> Check["检查写入顺序与时间戳"]
Check --> |基本有序| Append["顺序追加到当前时间窗口"]
Check --> |严重乱序| Reorder["应用层/流处理重排"]
Append --> Compress["激活列式压缩与索引"]
Reorder --> Compress
Compress --> Schedule["XXL-Job 定时归档"]
Schedule --> Export["taosdump 导出"]
Export --> Zip["压缩为 ZIP"]
Zip --> Restore["Python 有序批量重写入归档库"]
Restore --> End(["结束"])

图表来源

章节来源

MySQL 分表策略与分区工具

  • 水平分表
    • 活动日志按日期分表:AppActivityJob 按日期创建/维护分表,并在表上按 partition_index 进行 LIST 分区,分区数量覆盖 0~149
    • 规则关联表按业务域与 MAC 分区:MacPartitionUtil 提供按父表 ID 与 MAC 的高两位/低两位分区号计算,最终分区号为 1010~1939 的组合
  • 垂直分表
    • 通过将宽表拆分为多个窄表,按字段访问热点与生命周期分离,降低单表宽度与 IO 压力
  • 分表键选择
    • 活动日志:partition_index 作为分区键,来源于业务域与时间维度的组合
    • 规则关联表:partition_index 作为分区键,来源于父表 ID 与 MAC 的哈希组合
  • 查询优化
    • 明确分区键参与查询条件,避免全表扫描
    • 使用分区裁剪:WHERE 条件命中具体分区,减少扫描范围
    • 定期维护:重建分区统计信息,保持查询计划最优

Mermaid Diagram Code:

flowchart TD
A["输入:父表ID/子表ID 或 MAC 地址"] --> B{"是否传入父表ID?"}
B --> |是| C["计算高两位分区号<br/>getHighPartition(id)"]
B --> |否| D["计算低两位分区号<br/>getLowPartition(mac)"]
C --> E["组装最终分区号<br/>高两位*100 + 低两位"]
D --> E
E --> F["返回分区号用于分表/分区键"]

图表来源

章节来源

数据迁移方案与查询优化

  • 迁移方案
    • TDengine:通过 XXL-Job 调度,使用 taosdump 导出热表数据,Python 脚本按天有序批量重写入归档库,实现“热数据乱序写入 → 定期 ETL 清洗 → 归档数据有序重写”
    • MySQL:按日期滚动创建分表,配合 LIST 分区键 partition_index,实现按业务域与时间维度的快速裁剪
  • 查询优化
    • 明确分区键参与过滤条件,避免跨分区扫描
    • 对高频查询字段建立合适索引,结合分区裁剪提升性能
    • 对超大表采用分区裁剪 + 二级索引 + 读写分离策略

Mermaid Diagram Code:

sequenceDiagram
participant S as "业务服务"
participant J as "XXL-Job"
participant T as "TDengine 节点"
participant P as "Python 脚本"
S->>J : 触发归档任务
J->>T : taosdump 导出指定日期数据
T-->>J : 输出 CSV 文件
J->>P : 上传并执行有序重写脚本
P->>T : 按天/批量有序写入归档库
T-->>P : 写入完成
P-->>J : 返回统计结果
J-->>S : 更新归档记录状态

图表来源

章节来源

数据一致性与扩容策略

  • 一致性
    • TDengine:通过“有序写入 + 归档重写”恢复压缩与索引优势,降低碎片与小块,提升整体一致性
    • MySQL:通过分区键与分区裁剪,确保写入与查询命中目标分区,减少跨分区事务复杂度
  • 扩容策略
    • TDengine:按业务域与时间维度扩展超级表子表,归档库按月/季度滚动,结合 taosdump 与有序重写实现平滑扩容
    • MySQL:按日期滚动分表 + LIST 分区,新增分区键组合以承载新增业务域或时间窗口

章节来源

依赖关系分析

  • 组件耦合
    • AppActivityJob 依赖 JdbcTemplate 与业务服务,负责按日期创建/维护分表与分区
    • MacPartitionUtil 为规则关联表提供分区号计算,SQL 分区表定义与之对应
    • DeviceRuntimeCountJob 依赖远程 SSH 与 taosdump,负责 TDengine 数据库的影子库创建与数据迁移
    • VisitMinuteDO 为 TDengine 超级表与子表命名与标签提供依据
  • 外部依赖
    • TDengine:taosdump、SSH 远程执行
    • XXL-Job:调度与任务编排
    • MySQL:InnoDB 分区与索引

Mermaid Diagram Code:

graph LR
AppActivityJob --> Jdbc["JdbcTemplate"]
AppActivityJob --> PartitionIdx["partition_index"]
MacPartitionUtil --> SQLDef["rule_*_item 分区定义"]
DeviceRuntimeCountJob --> SSH["SSH 远程执行"]
DeviceRuntimeCountJob --> TaosDump["taosdump 导出"]
VisitMinuteDO --> TDMapper["TDengine Mapper"]

图表来源

章节来源

性能考量

  • TDengine
    • 有序写入显著提升压缩比与查询性能;乱序写入导致索引与块管理开销增大,压缩比恶化
    • 通过归档重写恢复列式压缩与索引优势,降低磁盘占用与查询延迟
  • MySQL
    • LIST 分区 + 分区键裁剪可显著减少扫描范围;建议对高频查询字段建立合适索引
    • 按日期滚动分表可实现热点数据与历史数据分离,提升写入与查询效率

[本节为通用性能讨论,无需特定文件引用]

故障排查指南

  • MySQL 分区异常
    • 当分区号不符合规范(如低两位不在 10~99)时,MacPartitionUtil 抛出 MysqlPartitionException,需检查父表 ID 或 MAC 的哈希计算
  • TDengine 写入异常
    • 若发现压缩比异常升高或磁盘占用激增,应检查写入顺序与时间戳,必要时触发归档任务进行有序重写
  • 数据迁移失败
    • 检查 SSH 连接与 taosdump 命令执行权限,确认远程主机可达与认证配置正确

章节来源

结论

  • 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

[本节为补充说明,无需特定文件引用]

用户文档
AI 助手
Agent 列表
请选择一个 Agent 开始对话
AI 问答