Anvil Career
Back to Blog
DEVELOPMENT TUTORIAL

MongoDB Query Optimization for Placement Portfolios: How to Go From COLLSCAN to IXSCAN and Prove You Understand Database Performance

10 min read

The MongoDB query that works fine on your laptop with 50 documents will collapse under a production workload of 50,000. This is not a MongoDB problem. It is an indexing problem, and it is the single most common performance mistake in student portfolios. A recruiter who reviews your code may not notice that your queries are unindexed. But an interviewer who asks "how would you optimize a slow API endpoint" will immediately test whether you reach for indexes as your first optimization tool. If your answer is "add more RAM" or "switch to PostgreSQL," you have failed the database performance question because you did not start with the zero-cost optimization that every database provides.

THE DATABASE PERFORMANCE FUNDAMENTAL

Every database query either uses an index (IXSCAN in MongoDB, Index Scan in PostgreSQL) or scans the entire collection/table (COLLSCAN in MongoDB, Sequential Scan in PostgreSQL). An index lookup on a field that is indexed is O(log n). A full collection scan is O(n). For 50 documents, the difference is negligible. For 50,000 documents, the indexed query returns in 2–5ms while the full scan takes 200–500ms. For 5 million documents, the indexed query still returns in 5–10ms while the full scan takes 3–10 seconds. Indexes are not optional. They are the difference between an application that works and one that times out. And they take 10 seconds to create.

How to Read a MongoDB Explain Output

The explain() method is your primary diagnostic tool. Run db.collection.find({ field: value }).explain("executionStats") in the MongoDB shell or Compass. The output tells you everything you need to know about your query performance. Look for three fields: winningPlan.stage — if this says COLLSCAN, your query is scanning every document. If it says IXSCAN, your query is using an index. executionStats.executionTimeMillis — the actual time the query took. executionStats.totalDocsExamined vs nReturned — if these numbers are far apart (examined 50,000, returned 5), your index exists but is not selective enough.

The most common indexing mistakes in student projects: indexing only on the _id field (MongoDB does this automatically, and it helps only for _id lookups), creating an index but querying on a different field (the index on "email" does nothing for a query on "username"), and creating single-field indexes when a compound index is needed (a query that filters on both "status" and "createdAt" needs a compound index on { status: 1, createdAt: -1 }, not two separate single-field indexes).

MONGODB QUERY PERFORMANCE: BEFORE AND AFTER INDEXING

SCENARIO WITHOUT INDEX WITH INDEX
Find user by email (50K users) COLLSCAN, ~180ms IXSCAN on {email:1}, ~2ms
Filter orders by status + date (100K orders) COLLSCAN, ~450ms IXSCAN on {status:1, createdAt:-1}, ~5ms
Sort products by price (10K products) COLLSCAN + in-memory sort, ~120ms IXSCAN on {price:1}, sorted by index, ~3ms

Adding Indexes to Your Existing Portfolio Project

Open your project. Identify every database query your application makes. For each query, look at the fields used in the filter (the first argument to find()), the sort specification, and any fields used in $lookup or $match stages of aggregation pipelines. Create an index for each query pattern. The MongoDB shell command is: db.collection.createIndex({ field1: 1, field2: -1 }). 1 means ascending, -1 means descending (matters only for compound indexes where the query sorts on that field). In Mongoose, add index: true to your schema definition for single-field indexes, or use schema.index({ field1: 1, field2: -1 }) for compound indexes.

After adding indexes, run .explain("executionStats") on the same queries. Verify that winningPlan.stage is now IXSCAN and executionTimeMillis has dropped. Document the before-and-after performance numbers in your README. A table showing "Query X: 180ms → 2ms after adding index on {field}" is exactly the kind of engineering evidence that interviewers want to see. It proves you identified a performance problem, diagnosed it with the database's diagnostic tools, applied the correct fix, and measured the improvement. That is the performance optimization loop that senior engineers execute daily, and demonstrating it in a student project is a strong signal.

THE 30-MINUTE DATABASE AUDIT

Open your project's database. Run every query your application makes with .explain("executionStats"). For any query where winningPlan.stage is COLLSCAN, create the appropriate index. Document the before-and-after times in a performance section of your README. This 30-minute exercise adds a dimension to your portfolio that 90% of student projects lack: evidence that you think about performance and know how to use database diagnostic tools to improve it. The recruiter may not understand MongoDB Explain output. They will understand the before-and-after numbers. And they will recognize that a candidate who optimizes queries without being asked is a candidate who thinks like an engineer.