Script Valley
MongoDB: Complete Course
Indexing and Query PerformanceLesson 3.1

How MongoDB indexes work and why queries slow down without them

collection scan vs index scan, B-tree index structure, index entry, query explain plan, COLLSCAN vs IXSCAN, nReturned vs totalDocsExamined

Without an index, MongoDB scans everything

COLLSCAN vs IXSCAN

Without an index, MongoDB performs a collection scan — it reads every single document in the collection to find matches. On a 10 million document collection, a query for one user by email examines all 10 million documents. With an index, the same query reads 1 document via a B-tree lookup. This is the single biggest performance lever in MongoDB.

How B-tree indexes work

MongoDB's default indexes are B-trees. An index on the email field stores sorted email values alongside pointers back to their full documents. Lookups drop from O(n) to O(log n) — roughly 23 comparisons for 10 million documents instead of 10 million reads. Every secondary index adds storage overhead and a maintenance cost on every write.

// Always check the query plan before adding indexes
const plan = await db.collection('users')
  .find({ email: 'ada@example.com' })
  .explain('executionStats')

// BEFORE index — slow
// stage: 'COLLSCAN', totalDocsExamined: 1000000, executionTimeMillis: 320

// AFTER creating index on email:
await db.collection('users').createIndex({ email: 1 })

// stage: 'IXSCAN', totalDocsExamined: 1, executionTimeMillis: 1

The write trade-off

Each index maintains a separate B-tree structure. Every insert, update, or delete must update all relevant indexes. A collection with 15 indexes pays a heavy write penalty per operation. Profile before adding indexes, and regularly remove unused ones using db.collection('users').dropIndex('email_1') to keep write throughput healthy.

Up next

How to create single field and compound indexes in MongoDB

Sign in to track progress