Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Cambiar una clave de partición

Reshard a Collection

Nuevo en la versión 5.0.

La clave de partición ideal permite a MongoDB distribuir documentos de manera uniforme por todo el clúster mientras facilita patrones comunes de query. Una clave de partición subóptima puede provocar problemas de rendimiento o escalado debido a una distribución de datos desigual. A partir de MongoDB 5.0, puedes cambiar la clave de partición de una colección para modificar la distribución de tus datos en un clúster.

Nota

Antes de volver a fragmentar su colección, lea Solucionar problemas de clave de partición para obtener información sobre problemas comunes de rendimiento y escalado y consejos sobre cómo solucionarlos.

Antes de volver a dividir tu colección, asegúrate de cumplir los siguientes requisitos:

  • Tu aplicación puede tolerar un periodo de dos segundos en el que la colección que se está redistribuyendo bloquea los guardados. Durante el período en que las escrituras están bloqueadas, tu aplicación experimenta un aumento en la latencia. Si tu carga de trabajo no puede tolerar este requisito, considera refinando tu clave de partición en su lugar.

  • Su base de datos cumple con estos requisitos de recursos:

    • Espacio libre en almacenamiento: Asegúrate de que el espacio de almacenamiento disponible en cada partición en el cual se va a distribuir la colección sea al menos el doble del tamaño de la colección que deseas volver a compartir y su tamaño total de índice, dividido por el número de particiones.

      storage_req = ( ( collection_size + index_size ) * 2 ) / shard_count

      Por ejemplo, considera una colección que contiene 2 TB de datos y tiene un índice de 400 GB distribuido en cuatro particiones. Para realizar una operación de resegmentación en esta colección, cada partición necesitaría 1.2 TB de almacenamiento disponible.

      1.2 TB storage = ( ( 2 TB collection + 0.4 TB index ) * 2 ) / 4 shards

      Para cumplir con los requisitos de almacenamiento, es posible que deba actualizar al siguiente nivel de almacenamiento durante la operación de refragmentación. Puede reducir la capacidad una vez finalizada la operación.

    • E/S: Asegúrate de que tu capacidad de E/S esté por debajo del 50%.

    • Carga de la CPU: asegúrese de que la carga de su CPU esté por debajo del 80%.

    Importante

    La base de datos no exige estos requisitos. Si no se asignan suficientes recursos, pueden producirse las siguientes consecuencias:

    • la base de datos se queda sin espacio y se apaga

    • rendimiento reducido

    • La operación de refragmentación está tardando más de lo esperado

    Si tu aplicación tiene períodos de tiempo con menos tráfico, redistribuye tu colección durante ese tiempo si es posible.

  • Debe reescribir las queries de su aplicación para utilizar tanto la clave de partición actual como la nueva clave de partición.

    Tip

    Si tu aplicación puede tolerar tiempos de inactividad, puedes realizar estos pasos para evitar reescribir las queries de la aplicación para usar tanto la clave de partición actual como la nueva:

    1. Detén tu aplicación.

    2. Reescriba su aplicación para utilizar la nueva clave de fragmento.

    3. Espere hasta que se complete el nuevo particionamiento. Para supervisar el proceso de redistribución, utilice la etapa de $currentOp pipeline.

    4. Implementa tu aplicación reescrita.

    Antes de que se complete la reorganización de los fragmentos, las siguientes consultas devuelven un error si el filtro de consulta no incluye ni la clave de fragmento actual ni un campo único (como _id):

    Para un rendimiento óptimo, le recomendamos que también reescriba otras consultas para incluir la nueva clave de fragmento.

    Una vez completada la operación de refragmentación, puedes remover la clave de partición anterior de las consultas.

  • No existen procesos de creación de índices en curso. Utiliza db.currentOp() para comprobar si hay procesos activos de creación de índices:

    db.adminCommand(
    {
    currentOp: true,
    $or: [
    { op: "command", "command.createIndexes": { $exists: true } },
    { op: "none", "msg" : /^Index Build/ }
    ]
    }
    )

    En el documento de resultados, si el valor en el campo inprog es un arreglo vacío, no hay creaciones de índices en curso:

    {
    inprog: [],
    ok: 1,
    '$clusterTime': { ... },
    operationTime: <timestamp>
    }

Nota

El reenrutamiento es un proceso de guardar intensivo que puede generar tasas aumentadas de oplog. Puedes optar por:

  • defina un tamaño fijo para el oplog para prevenir el crecimiento sin límites del oplog.

  • aumente el tamaño de Oplog para minimizar la posibilidad de que uno o más nodos secundarios queden obsoletos.

Consulte la documentación del registro de operaciones del conjunto de réplicas para obtener más detalles.

Importante

Le recomendamos encarecidamente que consulte Acerca de esta tarea y lea la sección Pasos en su totalidad antes de volver a fragmentar su colección.

En una operación de refragmentación de una colección, un fragmento puede ser:

  • dador, que actualmente almacena los fragmentos para la colección particionada.

  • destinatario, que almacena nuevos fragmentos para la colección particionada en función de las claves de partición y zonas.

Una partición puede ser donante y receptor al mismo tiempo. El conjunto de particiones donantes es idéntico a las particiones receptoras, a menos que utilices zonas.

El servidor de configuración principal siempre es el coordinador de re-sharding e inicia cada fase de la operación de re-sharding.

1

Mientras esté conectado al mongos, emite un comando reshardCollection que especifique la colección a redistribuir y la nueva clave de partición:

db.adminCommand({
reshardCollection: "<database>.<collection>",
key: <shardkey>
})

MongoDB establece el número máximo de segundos para bloquear guardados en dos segundos y comienza la operación de redistribución de particiones.

2

Para supervisar la operación de redistribución, puedes utilizar la etapa de pipeline $currentOp:

db.getSiblingDB("admin").aggregate([
{ $currentOp: { allUsers: true, localOps: false } },
{
$match: {
type: "op",
"originatingCommand.reshardCollection": "<database>.<collection>"
}
}
])

Nota

Para ver los valores actualizados, es necesario ejecutar continuamente la pipeline anterior.

La $currentOp salida de la pipeline:

  • totalOperationTimeElapsedSecs: elapsed operation time en segundos

  • remainingOperationTimeEstimatedSecs: tiempo estimado restante en segundos para la operación de reestructuración actual. Se devuelve como -1 cuando comienza una nueva operación de reestructuración.

    Empezando en:

    • En MongoDB 5.0, pero antes de MongoDB 6.1, remainingOperationTimeEstimatedSecs solo está disponible en un fragmento de destinatario durante una operación de reorganización de fragmentos.

    • MongoDB 6.1, remainingOperationTimeEstimatedSecs también está disponible en el coordinador durante una operación de reasignación de particiones.

    La operación de redistribución realiza estas fases en orden:

    1. La fase de clonación duplica los datos de la colección actual.

    2. La fase de puesta al día aplica cualquier operación de guardar pendiente a la colección redistribuida.

    remainingOperationTimeEstimatedSecs se establece en una estimación de tiempo pesimista:

    • La estimación de tiempo de la fase de actualización se establece en el tiempo de la fase de clonación, que es un periodo relativamente largo.

    • En la práctica, si sólo hay unas pocas operaciones de escritura pendientes, el tiempo real de la fase de sincronización es relativamente corto.

[
{
shard: '<shard>',
type: 'op',
desc: 'ReshardingRecipientService | ReshardingDonorService | ReshardingCoordinatorService <reshardingUUID>',
op: 'command',
ns: '<database>.<collection>',
originatingCommand: {
reshardCollection: '<database>.<collection>',
key: <shardkey>,
unique: <boolean>,
collation: { locale: 'simple' }
},
totalOperationTimeElapsedSecs: <number>,
remainingOperationTimeEstimatedSecs: <number>,
...
},
...
]
3

A lo largo del proceso de rehashing, el tiempo estimado para completar la operación de rehashing (remainingOperationTimeEstimatedSecs) disminuye. Cuando el tiempo estimado está por debajo de dos segundos, MongoDB bloquea los guardados y completa la operación de rehashing. Hasta que el tiempo estimado para completar la operación de rezonado esté por debajo de dos segundos, la operación de rezonado no bloquea los guardados por defecto. Durante el período en que las escrituras están bloqueadas, tu aplicación experimenta un aumento en la latencia.

Una vez que el proceso de redistribución de particiones se haya completado, el comando de redistribución de particiones devuelve ok: 1.

{
ok: 1,
'$clusterTime': {
clusterTime: <timestamp>,
signature: {
hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0),
keyId: <number>
}
},
operationTime: <timestamp>
}

Para ver si la operación de repartición se completó correctamente, debes revisar la salida del método sh.status():

sh.status()

La sh.status() salida del método contiene una subsección databases para. Si la repartición se ha completado correctamente, la salida muestra la nueva clave de la partición para la colección:

databases
[
{
database: {
_id: '<database>',
primary: '<shard>',
partitioned: true,
version: {
uuid: <uuid>,
timestamp: <timestamp>,
lastMod: <number>
}
},
collections: {
'<database>.<collection>': {
shardKey: <shardkey>,
unique: <boolean>,
balancing: <boolean>,
chunks: [],
tags: []
}
}
}
...
]

Nota

Si la colección reestructurada utiliza Atlas Search, el índice de búsqueda quedará inaccesible cuando la operación de reorganización se complete. Se debe reconstruir manualmente el índice de búsqueda una vez que se complete la operación de redistribución de datos.

Puede forzar manualmente que la operación de redimensionamiento se complete emitiendo el comando commitReshardCollection. Esto es útil si la estimación actual de tiempo para completar la operación de resharding es una duración aceptable para el bloqueo de escrituras de tu colección. El comando commitReshardCollection bloquea las escrituras antes y fuerza la finalización de la operación de redistribución de instancias. El comando tiene la siguiente sintaxis:

db.adminCommand({
commitReshardCollection: "<database>.<collection>"
})

Puede abortar la operación de re-fragmentación durante cualquier etapa de la misma, incluso después de ejecutar,commitReshardCollection hasta que los fragmentos se hayan recuperado por completo.

Por ejemplo, si remainingOperationTimeEstimatedSecs no disminuye, puedes abortar la operación de resharding con el comando abortReshardCollection:

db.adminCommand({
abortReshardCollection: "<database>.<collection>"
})

Tras cancelar la operación, puedes reintentar la operación de resharding durante una ventana de tiempo con un menor volumen de escrituras. Si esto no es posible, añade más particiones antes de volver a intentarlo.

La duración mínima de una operación de redistribución de fragmentos siempre es de 5 minutos.

Se pueden reintentar las escrituras reintentables iniciadas antes o durante el reshardeo, durante y después de que la colección haya sido reshardeada, durante hasta 5 minutos. Después de 5 minutos es posible que no puedas encontrar el resultado definitivo del guardado y los intentos posteriores de volver a intentar el guardado fallan con un error IncompleteTransactionHistory.

Si se produce una conmutación por error primaria en un fragmento de un conjunto de réplicas o en un servidor de configuración, la operación de reorganización de los fragmentos se cancela.

Si una operación de reparticionamiento se interrumpe debido a una conmutación por error primaria, ejecute el comando antes de iniciar una nueva operación de cleanupReshardCollection reparticionamiento:

db.runCommand({
cleanupReshardCollection: "<database>.<collection>"
})

La operación de redistribución falla si los valores de _id no son globalmente únicos para evitar la corrupción de los datos de la colección. Los valores duplicados de _id también pueden impedir que la migración de fragmentos tenga éxito. Si tienes documentos con valores duplicados de _id, copia los datos de cada uno en un nuevo documento y luego elimina los documentos duplicados.

Volver

Refinar una clave de fragmento