As applications scale to millions of records, unindexed database queries degrade from millisecond execution times to severe CPU-bound bottlenecks. Whether operating document-based databases (MongoDB) or relational systems (PostgreSQL), effective indexing and query execution planning are essential for maintaining sub-millisecond data retrieval speeds.
This guide analyzes indexing mechanics, composite query structures, and query execution diagnostic tools across MongoDB and PostgreSQL.
Indexing Mechanics: B-Tree vs. Specialized Indexes
| Index Type | Database Support | Primary Use Case | Performance Trait |
|---|---|---|---|
| B-Tree / Single Field | MongoDB & PostgreSQL | Direct equality and range lookups (=, >, <, BETWEEN) |
Logarithmic lookup complexity $O(\log N)$ |
| Compound / Composite | MongoDB & PostgreSQL | Multi-field filtering, sorting, and aggregation constraints | Requires strict adherence to the ESR Rule |
| Partial / Filtered | MongoDB & PostgreSQL | Indexing a subset of documents that match a specific condition | Reduces index size and write overhead dramatically |
| GIN / Multikey | PostgreSQL (GIN) / MongoDB (Multikey) | Array fields, JSONB documents, and full-text search operators | Higher write overhead, optimized for containment queries |
The Compound Index Golden Rule: ESR (Equality, Sort, Range)
When creating compound indexes for queries containing filtering and sorting directives, order fields in the index definition according to the ESR Rule:
- E (Equality): Place exact-match filter fields first (e.g.,
status: 'ACTIVE',tenantId: 101). - S (Sort): Place fields used for ordering results second (e.g.,
sort({ createdAt: -1 })). - R (Range): Place range comparison fields last (e.g.,
age: { $gt: 25 },price < 500).
1. MongoDB Index Optimization & Analysis
// 1. Create Compound Index using ESR Rule
db.orders.createIndex({
tenantId: 1, // Equality
createdAt: -1, // Sort
amount: 1 // Range
});
// 2. Query utilizing the ESR Index
db.orders.find({
tenantId: "t_4091",
amount: { $gte: 100 }
}).sort({ createdAt: -1 });
// 3. Diagnose Query Plan using explain()
db.orders.find({
tenantId: "t_4091",
amount: { $gte: 100 }
}).sort({ createdAt: -1 }).explain("executionStats");
Key Metrics to Watch in MongoDB Execution Stats:
stage: 'IXSCAN': Indicates an index scan (Good). Avoidstage: 'COLLSCAN'(Full Collection Scan).totalDocsExamined: Should match or closely equalnReturned. High values mean an inefficient index.
2. PostgreSQL EXPLAIN ANALYZE & Partial Indexes
In PostgreSQL, full table scans (Seq Scan) on massive tables spike I/O usage. Use Partial Indexes to index only high-frequency active query subsets.
-- 1. Create a Partial Index on Unprocessed Tasks only
CREATE INDEX idx_unprocessed_tasks
ON tasks (priority DESC, created_at ASC)
WHERE status = 'PENDING';
-- 2. Execute Query with EXPLAIN ANALYZE execution timing
EXPLAIN ANALYZE
SELECT id, payload
FROM tasks
WHERE status = 'PENDING'
ORDER BY priority DESC, created_at ASC
LIMIT 50;
Deciphering PostgreSQL Query Plans:
Index Scan using idx_unprocessed_tasks: Direct B-Tree traversal for matching rows.Bitmap Index Scan: Combines index pointers before reading heap pages (efficient for medium selectivity).Seq Scan: Evaluates every row in the table sequentially — indicates a missing or unused index.
Production Indexing Best Practices
- Avoid Over-Indexing: Every index adds overhead to write operations (
INSERT,UPDATE,DELETE) because the database must update index trees synchronously. - Covering Queries: Whenever possible, project only fields present within the index itself so the database engine returns data directly from the index tree without fetching heap/document pages.
- Monitor Unused Indexes: Periodically query
pg_stat_user_indexesin PostgreSQL or run$indexStatsin MongoDB to identify and drop unused or redundant indexes.