Solution:
Root Cause: Suboptimal Compound Index Key Sequence (ESR Violation) Even when an index exists, placing Range fields before Equality or Sort fields forces MongoDB to scan a large index key subset (
IXSCAN). When range filters (such as
$gt,
$lt, or
$in) precede sort keys in a compound index, the query engine cannot use index ordering to satisfy the sort step. It falls back to an in-memory sort, leading to CPU thrashing and query timeouts under high read loads.
Step-by-Step Fix: 1 Reorder Compound Index Keys Following the ESR Pattern:
Structure compound index keys strictly in this order: 1 Equality : Exact match fields (e.g., tenantId: "123", active: true).
2 Sort : Order-by fields matching query sort direction (e.g., priority: -1).
3 Range : Range filter fields (e.g., updatedAt: { $gte: start }).
2 Build the Optimized ESR Index:
Execute index creation with the corrected field sequence: Copy
javascript
db.tasks.createIndex({ tenantId: 1, priority: -1, updatedAt: 1 }, { background: true });
3 Drop Obsolete or Redundant Indexes:
List existing collection indexes: Copy
javascript
db.tasks.getIndexes();
Remove redundant single-field or incorrectly ordered indexes to reduce write amplification: Copy
javascript
db.tasks.dropIndex("tenantId_1_updatedAt_1");