Índices y migraciones en MongoDB | Nicolás Garzón
Inicio Wiki MongoDB Índices y migraciones Volver a MongoDBMongoDB
Índices y migraciones Explica cómo crear, ocultar, validar y retirar índices durante cambios de schema o consultas sin provocar bloqueos, regresiones o consumo innecesario.
Última actualización Actualizada 25 de jul de 2026
Los índices también evolucionan y deben migrarse como infraestructura de producción. Crear, reemplazar, ocultar o eliminar un índice afecta CPU, disco, cache, replication, backups y latencia de escritura. El procedimiento correcto coordina datos, aplicación y topología.
Nota anteriorMigraciones de datos Nota siguiente Roles y autorización Texto
Copiar query nueva
→ índice nuevo
→ build y observación
→ despliegue de lectores
→ retirada controlada del índice viejoNo elimines un índice porque “parece redundante” ni crees uno unique antes de comprobar los datos.
Antes del build documenta:
query shapes que servirá;
filtro, sort y projection;
tamaño estimado;
impacto en writes;
espacio temporal;
topología;
ventana operativa;
criterio de abortar;
cómo verificar uso.
JavaScript
Copiar db. orders. createIndex ( {
businessId : 1 ,
status : 1 ,
createdAt : - 1 ,
_id : - 1
} , {
name : 'orders_by_status_created_at'
} ) ; Un index build necesita leer datos y construir claves. Puede provocar:
alto I/O;
presión de cache;
espacio temporal;
replication lag;
más oplog por writes concurrentes;
mayor duración de backups;
latencia variable.
El comportamiento exacto del build y su coordinación entre replica set members depende de la versión. Consulta la documentación del servidor objetivo y prueba en staging con volumen parecido.
No uses únicamente el tamaño final estimado. Reserva margen para:
estructura en construcción;
índice anterior coexistiendo;
data files;
journal;
oplog;
snapshots;
crecimiento durante el build.
Un disco cercano al límite puede convertir una optimización en incidente.
Crear un índice unique requiere auditar duplicados:
JavaScript
Copiar db. users. aggregate ( [
{
$group : {
_id : {
businessId : '$businessId' ,
email : '$normalizedEmail'
} ,
count : { $sum : 1 } ,
ids : { $push : '$_id' }
}
} ,
{ $match : { count : { $gt : 1 } } }
] ) ; Después debes decidir qué duplicado es válido, corregir referencias y bloquear nuevos duplicados mientras limpias.
desplegar normalización y validación;
detectar y resolver duplicados;
impedir nuevas carreras mediante transición controlada;
crear unique index;
capturar duplicate key como conflicto de dominio;
verificar writers externos.
Para unicidad solo entre documentos activos:
JavaScript
Copiar db. products. createIndex (
{ businessId : 1 , sku : 1 } ,
{
unique : true ,
partialFilterExpression : {
deletedAt : null
}
}
) ; Antes de migrar prueba documentos missing, null, restauraciones y cambios de estado que entren al filtro parcial.
JavaScript
Copiar { businessId : 1 , createdAt : - 1 } JavaScript
Copiar { businessId : 1 , status : 1 , createdAt : - 1 } No elimines el anterior primero. Crea el nuevo, verifica que las queries lo usan y después evalúa el antiguo.
Durante coexistencia hay más coste de escritura. Mantén la ventana corta pero suficiente para observar tráfico real.
Un índice hidden sigue manteniéndose en cada write, pero deja de ser elegible normalmente por el planner. Es útil para ensayar retirada:
JavaScript
Copiar db. orders. hideIndex ( 'old_index_name' ) ;
medir uso previo;
ocultar;
observar latencia, scans y CPU;
probar query shapes críticas;
desocultar si hay regresión;
eliminar solo después de la ventana.
Hidden no mide el ahorro de write amplification porque el índice todavía se actualiza.
Eliminar libera almacenamiento y reduce coste futuro, pero puede causar:
COLLSCAN;
sorts bloqueantes;
regresiones de jobs poco frecuentes;
impacto en endpoints estacionales;
cambios de plan inesperados.
Revisa no solo métricas recientes. Considera procesos mensuales, cierres contables, exports y runbooks de incidentes.
JavaScript
Copiar { businessId : 1 }
{ businessId : 1 , status : 1 } El segundo puede servir algunas queries del primero por prefix. Pero no son equivalentes si difieren en:
unique;
partial filter;
sparse;
collation;
TTL;
hidden state;
sharding requirements;
sort útil.
No elimines por comparación textual únicamente.
La aplicación nueva puede requerir un índice que todavía no terminó de construirse. Orden recomendado:
Texto
Copiar crear índice
→ esperar disponibilidad
→ verificar explain
→ desplegar queryPara rollback, conserva temporalmente el índice usado por la versión anterior.
Un backfill puede necesitar:
JavaScript
Copiar { schemaVersion : 1 , _id : 1 } Documenta que es temporal. Después del backfill:
confirma cero pendientes;
detén el job;
observa otras dependencias;
oculta;
elimina.
Los índices temporales olvidados se vuelven coste permanente.
Un índice con nueva collation es una estructura diferente. Crea el nuevo, actualiza queries con collation compatible, valida igualdad y sort, y después retira el anterior.
Con unique, audita duplicados según las nuevas reglas lingüísticas.
Antes del build revisa todo el schema. Si un compound incluye dos paths que pueden ser arrays en un mismo documento, puede fallar. Un futuro cambio de schema también puede impedir writes.
Mide claves generadas por documentos outlier.
progreso del build;
replication lag;
disco;
estado de voting members;
elections;
oplog window.
No programes varios builds pesados y mantenimiento simultáneamente. Conserva mayoría disponible.
el índice debe construirse en todos los shards;
capacidad y duración pueden diferir;
un shard outlier domina el tiempo;
unique indexes tienen reglas de shard key;
mongos y FCV deben ser compatibles;
el balancer puede competir por recursos.
Un build interrumpido puede necesitar cleanup o reintento según versión. El runbook debe incluir:
cómo observar estado;
qué errores son recuperables;
cuándo abortar;
cómo comprobar consistencia;
cómo reintentar;
a quién escalar.
No reinicies nodos ciegamente durante un build.
JavaScript
Copiar db. orders. find ( filter)
. sort ( sort)
. limit ( 20 )
. explain ( 'executionStats' ) ;
índice elegido;
keys/docs examined;
sort;
latencia bajo carga;
plan stability;
writes;
tamaño del índice;
cache.
crear unique sin limpiar duplicados;
eliminar antes de desplegar el reemplazo;
confiar solo en uso de siete días;
construir varios índices grandes simultáneamente;
no reservar disco;
olvidar hidden indexes;
dejar índices temporales;
ignorar secondaries y oplog;
usar hint permanente para forzar adopción.
Captura queries y explain actual.
Estima tamaño y coste.
Prueba build en staging.
Monitorea todos los miembros.
Verifica query nueva.
Oculta índice viejo.
Observa una ventana representativa.
Prueba rollback.
Elimina de forma controlada.
Audita índices restantes.
Los índices tienen lifecycle. Se crean antes de que los necesite el código, se verifican con queries reales y se retiran después de una prueba reversible. Unique, collation, multikey y sharding añaden precondiciones. Cada cambio debe proteger disco, replication y capacidad de rollback.
Comprueba lo aprendido
¿Qué debes medir antes de un index build?
¿Por qué unique necesita auditoría de datos?
¿Qué permite un hidden index?
¿Por qué no eliminar primero el índice antiguo?
¿Qué cambia en sharding?
¿Cómo retirarías un índice temporal?