Skip to content

MongoJobExecutionDao.findRunningJobExecutions issues N+1 MongoDB queries #5356

@Wordbe

Description

@Wordbe

Bug description

MongoJobExecutionDao.findRunningJobExecutions() issues N+1 MongoDB queries, where N is the total number of JobInstance records for a given job name.

The current implementation iterates over every JobInstance and issues a separate MongoDB query for each one:

for (JobInstance jobInstance : jobInstances) {
    Query query = query(
            where("jobInstanceId").is(jobInstance.getId()).and("status").in("STARTING", "STARTED", "STOPPING"));
    this.mongoOperations.find(query, ...); // called N times
}

For a job with 1,000 historical instances but only 1 running execution, this results in 1,001 MongoDB queries.

In contrast, the JDBC implementation uses a single JOIN query:

SELECT E.JOB_EXECUTION_ID
FROM BATCH_JOB_EXECUTION E, BATCH_JOB_INSTANCE I
WHERE E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID AND I.JOB_NAME=? AND E.STATUS IN ('STARTING', 'STARTED', 'STOPPING')

Environment

  • Spring Batch version: main branch (6.x)
  • Database: MongoDB

Expected behavior

The method should use a single batch query with $in operator instead of N individual queries:

Map<Long, JobInstance> jobInstanceMap = new HashMap<>();
for (JobInstance jobInstance : jobInstances) {
    jobInstanceMap.put(jobInstance.getId(), jobInstance);
}
Query query = query(
        where("jobInstanceId").in(jobInstanceMap.keySet()).and("status").in("STARTING", "STARTED", "STOPPING"));
this.mongoOperations.find(query, ...); // called once

This reduces the query count from 1+N to 2, regardless of how many historical job instances exist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions