Rendimiento y optimización en MongoDB | Nicolás Garzón
Inicio Wiki MongoDB Rendimiento y optimización Volver a MongoDBMongoDB
Rendimiento y optimización Explica cómo optimizar MongoDB desde access patterns, consultas, índices, proyecciones, tamaño de documentos, memoria, red y distribución de carga.
Última actualización Actualizada 25 de jul de 2026
Optimizar MongoDB significa reducir el trabajo necesario para cumplir un requisito, no perseguir una métrica aislada. El orden correcto es medir el síntoma, localizar la capa responsable, cambiar una hipótesis y volver a medir.
Nota anteriorJournaling y durabilidad Nota siguiente Conexiones y pooling Texto
Copiar SLO incumplido
→ endpoint y query shape
→ explain + profiler
→ schema/índice/query/pool/storage
→ prueba comparativa
→ despliegue y observaciónAgregar hardware o shards antes de corregir scans, documentos y acceso solo distribuye el problema.
latencia alta;
throughput insuficiente;
timeouts;
CPU;
disco;
cache pressure;
lag;
pool wait;
coste;
variabilidad p99.
“MongoDB está lento” no es una hipótesis accionable. Identifica endpoint, operación, frecuencia, tenant y momento.
Captura filtro, sort, projection, limit y collation reales. Usa:
JavaScript
Copiar db. orders. find ( filter, projection)
. sort ( sort)
. limit ( 20 )
. explain ( 'executionStats' ) ; Compara nReturned, keys/docs examined, bounds, FETCH y SORT. Un índice usado puede seguir recorriendo cientos de miles de claves.
Un buen índice combina equality, sort y range según la query. Evita:
índice por cada campo;
compounds gigantes;
redundancia;
multikey sobre arrays ilimitados;
cobertura indiscriminada.
Mide el coste en writes, cache y disco. Usa hidden indexes para retirar de forma reversible.
Un documento enorme obliga a leer y reescribir más datos. Revisa:
arrays sin límite;
historial embebido;
blobs;
campos raramente usados;
subdocumentos que tienen lifecycle separado;
snapshots duplicados innecesarios.
Aplican subset, bucket, outlier o referencias según workload. No normalices por dogma.
Devuelve solo lo necesario:
TypeScript
Copiar orders. find ( filter, {
projection: {
status: 1 ,
total: 1 ,
createdAt: 1
}
} ) ; Reduce red y deserialización, pero no siempre evita leer documentos. Para eso necesita covered query compatible.
skip profundo obliga a recorrer resultados previos. Prefiere cursor pagination:
JavaScript
Copiar {
businessId,
$or : [
{ createdAt : { $lt : cursor. createdAt } } ,
{
createdAt : cursor. createdAt,
_id : { $lt : cursor. id }
}
]
} Con índice {businessId:1, createdAt:-1, _id:-1} y sort estable.
Reduce cardinalidad temprano:
$match primero cuando sea posible;
$project campos necesarios;
evita $unwind explosivo;
indexa foreign field de $lookup;
limita $facet;
revisa sort/group y disk spill;
materializa reportes frecuentes.
Optimizar un pipeline implica medir documentos entre stages, no solo duración total.
Writes lentos pueden deberse a:
filtro sin índice;
muchos índices;
documento grande;
contention;
write concern;
validator;
journaling y disco;
transacción larga.
Usa operadores atómicos y evita reemplazar documentos completos. Agrupa en batches razonables, no en una transacción enorme.
La query puede ser rápida en servidor pero el request esperar una conexión. Mide:
pool wait;
checkout timeout;
server selection;
conexiones nuevas;
DNS/TLS;
bytes enviados;
región entre app y cluster.
Reutiliza MongoClient. Un cliente por request crea tormentas y TLS overhead.
Relaciona p99 con cache eviction y disk reads. Mitigaciones:
índices mínimos;
aislar analytics;
projection/subset;
memoria;
materialized views;
datos fríos separados.
No exige que toda la base quepa en RAM.
Un contador o documento global puede serializar writes. Alternativas:
particionar contador;
buckets;
eventos y agregación;
reducir frecuencia;
diseñar por tenant.
Las transacciones no eliminan contention y pueden aumentar retries.
Considera sharding cuando un replica set optimizado no sostiene capacidad o localidad. Antes valida:
shard key;
queries targeted;
tenant outliers;
uniqueness;
balancer;
cross-shard transactions.
Scatter-gather multiplica una query ineficiente.
Usa datos y distribución representativos:
caso típico, p95 y outlier;
cold y warm cache;
concurrencia;
writes y reads combinados;
failover;
payload real;
duración suficiente.
No compares una query aislada en laptop con producción.
define baseline y SLO;
cambia una variable;
prueba correctness;
mide reads y writes;
revisa regresiones;
despliega gradualmente;
observa p95/p99;
conserva rollback;
documenta decisión;
elimina workaround temporal.
índice mejora promedio y empeora writes;
tenant outlier cambia plan;
cache caliente oculta scan;
hint fija un plan degradable;
autoscaling oculta regresión;
projection rompe contrato;
materialized view queda atrasada;
pool mayor satura servidor.
optimizar sin SLO;
mirar solo tiempo de explain;
añadir índices sin retirar otros;
aumentar pool arbitrariamente;
usar skip profundo;
shardear prematuramente;
ignorar correctness;
probar solo dataset pequeño;
cambiar varias cosas a la vez;
no medir coste total.
Reproduce el síntoma.
Mide endpoint y pool.
Ejecuta explain.
Revisa schema e índice.
Prueba propuesta con datos reales.
Mide writes y cache.
Ejecuta carga sostenida.
Prueba failover/outlier.
Despliega con observación.
Confirma SLO y elimina deuda.
El rendimiento surge de la combinación de schema, query shape, índices, pool, memoria, storage y topología. Optimiza el cuello medido y valida el resultado bajo distribución real. Más hardware es válido cuando el diseño ya es correcto; antes de eso solo compra tiempo.
Comprueba lo aprendido
¿Qué debes definir antes de optimizar?
¿Por qué IXSCAN no basta?
¿Cuándo usar cursor pagination?
¿Qué causa un hot document?
¿Qué debe incluir un benchmark?
¿Cuándo considerar sharding?