尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Doris动态分区参数dynamic_partition.start:机制、修改与踩坑实践

Doris动态分区参数dynamic_partition.start:机制、修改与踩坑实践 开年以来好几套 Doris 集群陆续要调整业务的数据保留周期其中改动最频繁的就是动态分区的时间窗口。先说结论dynamic_partition.start这个参数看着不起眼但它决定了分区表往前保留多少天的历史分区改错了轻则历史数据被提前清理重则分区长时间不创建导致导入任务直接报错。这篇文章就从参数机制、实际修改步骤、验证方法到踩坑排查完整过一遍。1. 动态分区的参数体系与偏移量的位置1.1 一组参数共同决定分区生命周期Doris 的动态分区功能Dynamic Partition不是靠单个参数工作的而是一组参数协同控制整个分区时间窗口。第一次接触这个功能的同学建议先把下面这张参数表存下来之后排查问题会频繁用到参数名默认值作用dynamic_partition.enabletrue是否开启动态分区dynamic_partition.time_unitDAY时间粒度可填 HOUR / DAY / WEEK / MONTHdynamic_partition.startInteger.MIN_VALUE保留的历史分区偏移量负数dynamic_partition.end1预创建的未来分区数量dynamic_partition.prefix无默认值动态分区名前缀如p_dynamic_partition.buckets10每个分区的分桶数dynamic_partition.create_history_partitionfalse是否开启自动创建历史分区这里面dynamic_partition.start就是文章标题里的偏移量。需要特别注意它的语义默认值在逻辑上等价于保留所有历史分区一旦你显式设置成一个具体的负数比如-7那就表示只保留从今天往前数 7 天范围内的分区更早的分区会被后台调度线程自动删除。1.2 偏移量在分区生命周期中的位置把整个动态分区机制拆开看它本质上是在做三件事预创建未来的分区、按需补建历史分区、清理过期的历史分区。偏移量管的是第三件事。预创建和清理这两个动作在时间轴上正好是相对的方向。end参数管未来决定调度器会预先建好几个分区start参数管过去决定调度器最多容忍多少个历史分区存在。两者组合起来才是完整的保留窗口。举个例子假设今天是2025-06-01你设置了START -3, END 2, TIME_UNIT DAY那么分区表内的合法分区范围就是保留的历史分区20250601T-0、20250531T-1、20250530T-2、20250529T-3预创建的未来分区20250602T1、20250603T2也就是说start -3表示保留到今天往前 3 个时间单位含今天一共 4 天的历史数据。这个含今天的细节特别容易弄混后面排查问题的时候会专门讲。2. 偏移量改动为什么会不生效调度机制先搞清楚2.1 FE 的定时调度是唯一执行入口很多人改完dynamic_partition.start之后发现分区没有被删除第一反应是参数没设置成功或者干脆重启 FE。实际上动态分区的所有操作——无论是预创建还是过期清理——都不是立刻触发的而是由 FE 内部的DynamicPartitionScheduler定时调度执行的。这个调度器默认每 10 分钟运行一次。也就是说你改完参数之后最快要等下一个调度周期才能看到分区变化。这个机制本身没什么问题但很多刚从其他数据库转过来的同学会踩坑以为 Doris 的动态分区是实时响应的。2.2 每一步都是为了给调度器减负稍微往深处想一层为什么 Doris 要把动态分区设计成定时调度而不是实时触发核心原因是分区表的元数据操作在 Doris 里属于比较重的操作。每个分区不仅有一条元数据记录还关联着对应的数据分片Tablet在 BE 节点上的分布信息。如果每次时间边界变化都立刻去增删分区在分区数量比较多、集群节点比较多的情况下会给 FE 和 BE 带来明显的元数据压力。定时调度相当于把操作批量化和错峰执行。实际运维中如果我需要调整偏移量并希望快速生效除了修改参数之外还会关注当前调度周期还剩多久必要的时候用ADMIN SHOW相关命令确认调度状态而不是干等着。2.3 调度器的判定逻辑调度器执行时的判定逻辑大致是这样的读取出当前动态分区表的配置。基于dynamic_partition.time_unit计算出当前时间边界。扫描该表现有的所有分区找出超出[当前时间 - start, 当前时间 end]范围的分区。超出范围的分区进入删除队列缺失的未来分区进入创建队列。逐个提交元数据变更任务。注意第 3 步这个扫描是全量扫描所以动态分区表的数量越多每个调度周期内要检查的分区元数据就越多。这也是为什么官方文档建议动态分区的数量不宜过多的原因。3. 实操修改 dynamic_partition.start 的完整链路3.1 修改前的状态确认动手之前先确认当前表的动态分区配置。命令很简单SHOW DYNAMIC PARTITION TABLES;这个命令会输出所有开了动态分区的表以及各自的配置。如果表多可以加 WHERE 条件过滤。我一般习惯把输出里的Start、End、TimeUnit、Prefix这几个字段先记下来改完之后方便对比。确认完动态分区表配置之后再确认一下目标表的当前分区情况SHOW PARTITIONS FROM 库名.表名;这里重点看两个字段PartitionName和Range。PartitionName 里包含了分区的时间信息Range 则给出实际的取值区间。这样能直观看到当前存在的分区范围跟你的预期是不是一致。3.2 执行修改的语法与示例动态分区参数的修改是在ALTER TABLE语句中完成的。以修改dynamic_partition.start为例ALTER TABLE 库名.表名 SET (dynamic_partition.start -7);如果你要同时调整多个参数可以直接一次性设置ALTER TABLE 库名.表名 SET ( dynamic_partition.start -7, dynamic_partition.end 3, dynamic_partition.time_unit DAY );语句执行成功之后建议立刻重新执行SHOW DYNAMIC PARTITION TABLES查看Start字段是否已经变成-7。这里有个容易被忽略的点修改参数本身只会更新 FE 中的元数据配置不会立刻触发分区删除真正的分区变更要等调度器下一个周期执行。3.3 验证修改生效的正确姿势改完之后怎么确认真的生效很多人的做法是等一段时间然后看分区有没有少。这个做法不太严谨因为分区可能因为别的原因没被删掉。我更推荐的做法是分三步验证第一步确认参数值已经更新通过SHOW DYNAMIC PARTITION TABLES或者查询information_schema中的相关表。第二步观察调度器是否执行了删除操作。可以在 FE 的日志中搜索DynamicPartitionScheduler相关关键字也可以直接看分区表的分区数量变化。第三步关键确认被删掉的分区确实是预期范围内的。比如你设置start -7那么往前数 8 天前的分区理论上都应该被清掉。如果发现保留的分区比预期多一天多半是时间边界算错了这个在下一节详细展开。4. 边界值容易踩的坑从一次真实事故说起4.1 事故背景有次接手一套新部署的 Doris 集群业务方要求数据保留 30 天我按照惯性设置了dynamic_partition.start -30。表面上看没有任何问题但过了几天之后业务反馈说某张表分区被提前删了查下来发现从配置上看完全正常但分区的边界计算方式跟我想的不一样。重新去核对官方文档和源码逻辑发现-30表示的是保留从今天往前 30 天含今天的分区也就是总共 31 个分区。这个逻辑本身并没错但问题出在调度器的判断条件上。当分区边界落在滚动窗口边缘时因为日期粒度是按天算的如果某天因为写入延迟或者导入分区的批次边界跟自然日不对齐就会出现该删的没删、不该删的少了一天这类情况。4.2 源码层面的边界判定逻辑Doris 动态分区的源码中分区时间边界的计算依赖于TimeUtils工具类。以 DAY 为粒度为例当前时间会被格式化到天这一层然后根据偏移量计算上下界。假如当前时间是2025-06-01 14:30:00那么时间下界最老保留分区是2025-06-01 00:00:00减去 7 天也就是2025-05-25 00:00:00时间上界最新预创建分区是2025-06-01 00:00:00加上 2 天也就是2025-06-03 00:00:00这个计算逻辑中分区是否保留的判断依据是分区的时间范围是否完全落在窗口内。举个具体的例子假设存在一个分区名叫p20250524Range 是[2025-05-24 00:00:00, 2025-05-25 00:00:00)因为分区的最小时间小于下界所以它会被删除。如果你设置start -7边界就在 5 月 25 日。此时p20250525这个分区Range[2025-05-25 00:00:00, 2025-05-26 00:00:00)正好落点在边界上是会被保留的。4.3 为什么说含今天是最大的坑网上很多教程把-7直接说成保留 7 天的数据这个说法其实是不准确的准确的说法是包含今天在内往前数 7 天也就是总共 8 个自然日。这个差异在日常操作中也许看不出什么但在数据校验或者对账场景下会带来困惑。比如业务方要求保留 7 天数据你设置了-7实际保留了 8 天多出来的那一天如果是敏感数据就会涉及数据留存周期超期的问题。所以我个人的建议是业务方跟你说保留 N 天时明确跟他确认是否包含今天。如果包含今天就设置-(N-1)如果不包含今天直接设置-N。沟通成本高一点点但避免后续无穷无尽的扯皮。4.4 改完 start 后的连锁影响小心分区不连续修改start只影响历史分区的清理动作不会影响到未来分区的预创建。听起来很简单但实际中有一个连锁反应很多人没预料到。当start从默认值改成-30之后调度器会开始清理超过 31 天的历史分区。如果你的业务会出现某天分区没有创建的情况比如调度链路故障、当天没有数据写入导致分区没有被触发创建那么清理操作会把本来就缺失的分区边界进一步压缩。更麻烦的是某些业务在下游读取数据时默认分区存在才去读取分区一旦缺失会产生空指针或者解析异常。这时候你以为只是改个保留周期实际上可能触发下游任务的隐性报错。因此改完start之后建议顺手检查一遍最近一个月历史分区是否连续。检查方式SELECT PartitionName, Range FROM information_schema.partitions WHERE TableName 库名.表名 ORDER BY PartitionName;如果发现中间缺了日期分区需要确认是本来就缺失还是被动态分区的清理策略删掉了。5. 特殊场景create_history_partition 与 start 的联动5.1 为什么有时候想保留更多历史分区反而建不出来Doris 从某个版本开始支持dynamic_partition.create_history_partition参数默认是false。打开之后调度器不仅会预创建未来的分区还会尝试自动补齐历史分区。但这里有个非常隐蔽的联动陷阱如果你把create_history_partition设为true同时又设置了一个比较大的负数start比如-365调度器会尝试一次性创建过去一年365 个的分区。在大表上这 365 个分区可能会瞬间产生成千上万个 Tablet直接打爆 FE 的元数据内存。有些同学为了省事在导入历史数据之前把create_history_partition打开数据导完再把历史分区删掉重置偏移量。这种做法不是不行但要控制节奏。我实际操作下来比较稳妥的方式是先设置一个很小的start比如-3配合create_history_partition true让调度器分批创建确认元数据压力可控之后再把start改成目标值。5.2 手动补历史分区与 start 的相互作用另一个常见场景是你有一批历史数据需要补导但start的值很小历史分区根本不在保留窗口内。这时候有两种做法。第一种做法是临时把start调大导完数据之后再把start调回来。这种做法风险在于如果忘记调回来调度器会自动把导进去的历史分区全部删掉。我见过不止一次这种情况数据导完了第二天一看分区被清空了。第二种做法是手动创建历史分区不依赖动态分区。先手动建好分区再导入数据。这种情况下即使start值很小调度器一般不会主动去删除手动创建的分区吗实际上会。只要动态分区表开启调度器在全量扫描时并不会区分某个分区是自动创建的还是手动创建的。只要超出窗口都会进入删除队列。所以如果你是手动补的历史分区且希望长期保留唯一的办法就是让start的范围覆盖到这些分区。没有别的捷径。6. 从一次线上事故还原完整排查链路6.1 事故现象某个周五下午业务反馈某张报表的数据少了一天。我登录 Doris 看了一下分区情况发现20250524这个分区不存在了而那天是有数据导入的。第一反应是导入任务出了问题但查了导入记录数据确实写成功了。然后又去查表的动态分区配置发现start被设置成了-7。按时间推算20250524恰好落在保留窗口边缘之外被调度器清理了。6.2 排查过程完整的排查链路是这样的第一步查SHOW DYNAMIC PARTITION TABLES确认start的值和时间粒度。第二步查SHOW PARTITIONS确认当前还存在哪些分区找到缺失的那一天。第三步查导入日志中的分区写入信息确认数据当时确实已经写成功。第四步关键对比分区删除时间和start参数修改时间。如果删除时间跟参数修改时间基本吻合基本就能锁定是start调整导致的过期清理。这个案例中业务方要求保留 7 天数据运维同学设置了start -7但业务方所说的7 天不包含当天实际需要 8 个自然日的数据。最终调整成start -8才符合要求。6.3 要养成的操作习惯经过这次事故我养成了几个操作习惯修改start之前先备份原参数值防止改完没生效还想还原回去的时候找不到原始值。修改完start之后在使用SHOW DYNAMIC PARTITION TABLES确认参数更新的同时也顺手拍一下当前分区列表的截图方便后续追踪。给分区创建任务的监控告警增加一项动态分区表的分区数量在短时间内大幅减少时触发告警。这能第一时间发现误删问题不用等业务来反馈。在运维文档里对每张分区表都写清楚数据保留周期和start 参数值的对应关系避免不同人对N 天理解不一致。7. 其他与 start 相关的参数调优思路7.1 end 与 start 的不对称设计前面提到end默认值是 1start默认是无穷小。这个设计其实是有意为之的。未来分区多创建几个没有实际成本因为数据没写入时分区是空的元数据开销也不算大。但历史分区如果无限保留持续增长的数据量会拖慢查询和导入性能。所以如果你发现某张表动态分区相关性能开始下滑优先检查start是不是被设成了一个特别大的负数。很多刚开始用 Doris 的团队习惯性把start设成-3650保留十年导致分区数量爆炸后续加节点也救不回来。一个分区表的分区数量建议控制在几百以内如果你有超过 1000 个分区查询计划生成阶段会变慢BE 在做多版本合并和 Compaction 时压力也会上升。7.2 time_unit 与 start 的配合time_unit的取值会影响start的语义。比如time_unit WEEK或MONTH时start的偏移量是按周或按月计算的。这里有一个细节需要注意当time_unit为 MONTH且分区前缀的格式可能同时包含年、月、日两层比如某些版本中 MONTH 粒度仍会生成多个日级子分区此时start -1并不代表只保留当前月的前一个月而可能还涉及子分区的二级边界。不同粒度之间的边界计算规则建议以官方文档为准在测试环境先验证再上生产。7.3 与导入频率的关系如果你的导入任务每个小时执行一次分区的time_unit却设置成 DAY那么start -3意味着水位的波动会被放大。因为小时级导入失败或者延迟不会立刻体现在分区上但一旦跨天就可能出现今天的分区还没建出来、昨天的分区被删了这种情况。处理思路有两种一是把time_unit调整成 HOUR 级让动态分区的时间窗口更小、更精准二是把start的绝对值稍微调大一点给导入任务留出缓冲时间。8. 最后再说一个操作习惯上的建议Doris 的动态分区功能在开源 OLAP 引擎里做得已经算很完善但因为配置项多且相互关联操作时稍不注意就埋雷。我个人最想强调的还是那句话设置start之前先确认业务方口中的保留 N 天是否包含今天再按需加减一。另外改完参数别急着走花两分钟执行一下SHOW DYNAMIC PARTITION TABLES和SHOW PARTITIONS做对比确认。这两条命令不费什么事但能避免改完没生效就重试、重试两次之后参数反而改错了这种低级问题。最后所有动态分区相关的变更都建议记录到变更清单里写明修改前的值、修改后的值、修改原因和预计生效时间。这样即使在三个月后回查也能快速定位到是哪一次变更引起的分区变化。
返回列表