liveBook · Manning

Index scan

As explained in MongoDB 8.0 in Action, Third Edition

An index scan is query execution that traverses index entries to locate documents matching query conditions.

An index scan traverses index keys to find matches for a query condition. In a MongoDB execution plan, it appears as IXSCAN. A typical plan passes matching keys to FETCH, which retrieves the documents; a collection scan appears as COLLSCAN instead. section 7.1.1 section 7.2.1

To check whether a query benefits from an index:

  • Create an index that matches the field being queried, such as db.movies.createIndex({ runtime: 1 }). section 7.2.1
  • Run db.movies.find({ runtime: 100 }).explain("executionStats"). Look for IXSCAN and its indexName under winningPlan. section 7.2.1
  • Compare nReturned with totalKeysExamined and totalDocsExamined. Examining few keys and documents relative to the results can indicate an efficient scan; also check executionTimeMillis. section 7.1.1

An index scan need not fetch documents. If an index contains the fields needed by both the filter and projection, a covered query can return results directly from index entries. Its plan shows IXSCAN beneath PROJECTION_COVERED and can report zero documents examined. Exclude _id when it is not in the index; a multikey index cannot cover a query that returns an array field. section 7.6.8

Index scans across an $or query

For db.movies.find({ $or: [{ year: 1914 }, { "imdb.rating": { $gt: 7 } }] }), each clause can use its own index—but every clause must have index support. A compound index beginning with year does not effectively support the rating clause on its own. Add db.movies.createIndex({ "imdb.rating": 1 }) to avoid the collection scan in this case. section 7.6.4

Listing 7.2 Execution-plan output structure
{
  "winningPlan": {
    "stage": "FETCH",
    "inputStage": {
      "stage": "IXSCAN",
      "indexName": "yourField_1",
      "keyPattern": {
        "yourField": 1
      },
      "indexBounds": {
        "yourField": [
          "[\"value\", \"value\"]"
        ]
      }
    }
  },
  "executionStats": {
    "nReturned": 1,
    "executionTimeMillis": 3,
    "totalKeysExamined": 1,
    "totalDocsExamined": 1
  }
}

Inspect how IXSCAN supplies keys to FETCH and how the plan reports index bounds and examined-key counts. section 7.1.1

db.movies.find(
{ year: 1914, "imdb.rating": { $gte: 7 } },
{ title: 1, year: 1, _id: 0 }
).explain("executionStats")

……
winningPlan: {
      stage: 'PROJECTION_COVERED',
      transformBy: { title: 1, year: 1, _id: 0 },
      inputStage: {
        stage: 'IXSCAN',
        keyPattern: { year: 1, title: 1, 'imdb.rating': 1 },
        indexName: 'year_1_title_1_imdb.rating_1'
……
  executionStats: {
    executionSuccess: true,
    nReturned: 2,
    executionTimeMillis: 0,
    totalKeysExamined: 4,
    totalDocsExamined: 0

Compare the covered-query plan: IXSCAN feeds PROJECTION_COVERED, with four keys examined and no documents examined. section 7.6.8

How MongoDB 8.0 in Action, Third Edition covers it

How deep it goes
Explains IXSCAN in execution plans and statistics, including FETCH and covered queries, without detailing the scan’s internal algorithm.
Examples
Uses indexed movie-runtime queries, separately indexed $or clauses, and a covered movie projection with zero documents examined.
What it assumes
Assumes basic MongoDB find filters while showing how to create an index and check its use with explain().
What you can do after
Diagnose/debug with explain("executionStats") to identify IXSCAN, inspect examined-key and document counts, and spot collection scans.
How it connects
Connects index scans to query plans, FETCH, collection scans, covered queries, compound indexes, and $or queries.

Also explained in

Compare how 3 books explain index scan →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of MongoDB 8.0 in Action, Third Edition. The section links point to the parts of the book it draws on.