You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带过滤的Joiners执行性能过慢,求优化方案

性能优化方案:替换过滤式连接为范围连接

你的代码性能差的核心原因是使用了Joiners.filtering(),这个操作会先对所有同Agent、同Permission的WorkingDay生成笛卡尔积,再在内存中过滤日期范围,数据量较大时会导致O(n²)的时间复杂度,性能急剧下降。

优化思路

用OptaPlanner支持的范围连接条件替代过滤式连接,让框架在连接阶段就过滤掉不符合日期范围的配对,避免全量笛卡尔积的生成,大幅减少需要处理的数据量。

同时调整分组逻辑,让统计逻辑更贴合“检查连续5天工作日”的需求:

优化后的代码

private Constraint fiveConsecutiveWorkingDaysMax(ConstraintFactory constraintFactory) {
    return constraintFactory
            .from(WorkingDay.class)
            .filter(WorkingDay::hasPermission)
            // 用范围连接替代过滤式连接,直接限制日期范围
            .join(WorkingDay.class,
                    Joiners.equal(WorkingDay::hasPermission),
                    Joiners.equal(WorkingDay::getAgent),
                    // wd2的日期 >= wd1日期减4天
                    Joiners.greaterThanOrEqual((wd1, wd2) -> wd2.getDayJava(), wd1 -> wd1.getDayJava().minusDays(4)),
                    // wd2的日期 < wd1的日期
                    Joiners.lessThan((wd1, wd2) -> wd2.getDayJava(), WorkingDay::getDayJava))
            // 按wd1分组,统计其窗口内的wd2数量
            .groupBy((wd1, wd2) -> wd1, ConstraintCollectors.countBi())
            // 当窗口内数量>=4时,说明加上wd1自身就是连续5天
            .filter((wd1, count) -> count >= 4)
            .penalizeConfigurable(FIVE_CONSECUTIVE_WORKING_DAYS_MAX);
}

额外优化建议

  • 确保WorkingDay的getAgent()、getDayJava()方法返回值的哈希和比较逻辑高效,避免不必要的计算开销。
  • 如果数据集很大,可以考虑为WorkingDay添加复合索引(比如Agent + hasPermission + dayJava),OptaPlanner能利用这类索引加速连接操作。
  • 原代码分组对象为wd2,统计的是有多少个wd1的窗口包含它,和业务需求不符;优化后改为按wd1分组,统计其前4天内的工作日数量,逻辑更贴合“禁止连续5天工作”的约束。

内容的提问来源于stack exchange,提问作者Raphawel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:01:22