Otimizando coleções fragmentadas no MongoDB com desfragmentação
Matt Panton, Garaudy Etienne, Ratika Gandhi8 min read • Published Feb 07, 2023 • Updated Feb 08, 2023
Avalie esse Artigo
Então, o que você faz se tiver um grande número de blocos em seu cluster fragmentado e quiser reduzir o impacto das migrações de blocos na latência do CRUD? Você pode usar a desfragmentação de collection!
Nesta publicação, abordaremos quando você deve considerar desfragmentar uma collection, os benefícios da desfragmentação para seu cluster fragmentado e abordaremos todos os comandos necessários para executar, monitorar e interromper a desfragmentação. Se você é novo em fragmentação ou deseja se atualizar sobre como o MongoDB oferece escalabilidade horizontal, confira o manual do MongoDB.
Uma coleção fragmentada é armazenada como "chunks," e um balanceador move os dados para manter uma distribuição igual de dados entre os fragmentos. No MongoDB 6.0, quando a diferença na quantidade de dados entre dois fragmentos é duas vezes o tamanho do bloco configurado, o balanceador do MongoDB migra automaticamente os fragmentos entre os fragmentos. Para coleções com um tamanho de bloco de 128MB, migraremos dados entre fragmentos se a diferença no tamanho dos dados exceder 256MB.
Toda vez que migra uma parte, o MongoDB precisa atualizar o novo local dessa parte em sua tabela de roteamento. A tabela de roteamento armazena a localização de todas as partes contidas em sua coleção. Quanto mais chunks houver em sua coleção, mais locais "" na tabela de roteamento e maior será a tabela de roteamento. Quanto maior a tabela de roteamento, mais tempo leva para atualizá-la após cada migração. Ao atualizar a tabela de roteamento, o MongoDB bloqueia as gravações em sua collection. Como resultado, é importante manter o número de partes da sua coleção no mínimo.
Ao mesclar o maior número possível de blocos por meio da desfragmentação, você reduz o tamanho da tabela de roteamento, reduzindo o número de blocos em sua coleção. Quanto menor for a tabela de roteamento, menor será a duração do bloqueio de gravação em sua coleção para migrações, mesclagens e divisões de partes.
Uma collection com um número excessivo de chunks é considerada fragmentada.


Neste exemplo, a collection de um cliente tem ~615K chunks em cada shard.
A desfragmentação é o conceito de mesclar blocos contíguos para reduzir o número de blocos em sua collection.

Em nosso mesmo exemplo, após a desfragmentação em 5de dezembro, o número de partes caiu para 650 partes em cada fragmento. O cliente conseguiu reduzir o número de partes em seu cluster por um fator de 1000.
A desfragmentação de uma collection deve ser considerada nos seguintes casos:
- Uma collection fragmentada contém mais de 20,000 chunks.
- Quando as migrações de chunks forem concluídas após a adição e remoção de shards.
O processo é composto de três fases distintas que ajudam a reduzir o número de chunks na collection escolhida. A primeira fase mescla automaticamente chunks mescláveis no mesmo fragmento. A segunda fase migra chunks menores para outros shards para que possam ser mesclados. A terceira fase verifica o cluster uma última vez e mescla todos os blocos mescláveis restantes que residem no mesmo fragmento.
Observação: não modifique o valor de chunkSize enquanto a desfragmentação estiver sendo executada, pois isso pode levar a um comportamento inadequado.
Na fase um do processo de desfragmentação, o MongoDB verifica cada shard no cluster e mescla todos os chunks mescláveis que residem no mesmo shard. O tamanho dos dados dos chunks resultantes é armazenado para a próxima fase do processo de desfragmentação.
Depois que a fase um for concluída, pode haver alguns pequenos pedaços restantes. Os chunks que têm menos de 25% do tamanho máximo de chunks definidos são identificados como chunks pequenos. Por exemplo, com o tamanho de bloco padrão do MongoDB de 128MB, todos os blocos de 32MB ou menos seriam considerados pequenos. O balancer então tenta encontrar outros chunks em cada shard para determinar se eles podem ser mesclados. Se dois chunks puderem ser mesclados, o menor dos dois será movido para ser mesclado com o segundo chunk. Isso também significa que quanto maior o tamanho do bloco configurado, mais pedaços de "small" você pode mover e mais você pode desfragmentar.
Nessa fase, o balanceador escaneia todo o cluster para encontrar quaisquer outros blocos mescláveis que residam no mesmo fragmento e os mescla. O processo de desfragmentação agora está completo.
Se você tiver uma coleção altamente fragmentada, poderá desfragmentá-la emitindo um comando para iniciar a desfragmentação por meio das opçõesconfigureCollectionBalancing.
1 db.adminCommand( 2 { 3 configureCollectionBalancing: "<database>.<collection>", 4 defragmentCollection: true 5 } 6 )
Durante todo o processo, você pode monitorar o status da desfragmentação executando balancerCollectionStatus. Consulte nosso manual balancerCollectionStatus para obter um exemplo detalhado sobre a saída do comando balancerCollectionStatus durante a desfragmentação.
A desfragmentação de uma coleção pode ser interrompida com segurança a qualquer momento durante qualquer fase emitindo um comando para interromper a desfragmentação por meio das opçõesconfigureCollectionBalancing.
1 db.adminCommand( 2 { 3 configureCollectionBalancing: "<database>.<collection>", 4 defragmentCollection: false 5 } 6 )
Vamos desfragmentar uma coleção chamada
"airplanes"
no banco de dados do "vehicles"
, com o tamanho de bloco padrão atual de 128MB.1 db.adminCommand( 2 { 3 configureCollectionBalancing: "vehicles.airplanes", 4 defragmentCollection: true 5 })
Isso iniciará o processo de desfragmentação. Você pode monitorar o processo usando o comandobalancerCollectionStatus . Aqui está um exemplo da saída em cada fase do processo.
1 { 2 "balancerCompliant": false, 3 "firstComplianceViolation": "defragmentingChunks", 4 "details": { 5 "currentPhase": "mergeAndMeasureChunks", 6 "progress": { "remainingChunksToProcess": 1 } 7 } 8 }
Como essa fase do processo de desfragmentação contém múltiplas operações, como
mergeChunks
e dataSize
, o valor do campo remainingChunksToProcess
não mudará quando a operaçãomergeChunk
tiver sido concluída em um bloco, mas a operação dataSize não estiver concluída para o mesmo pedaço.1 { 2 "balancerCompliant": false, 3 "firstComplianceViolation": "defragmentingChunks", 4 "details": { 5 "currentPhase": "moveAndMergeChunks", 6 "progress": { "remainingChunksToProcess": 1 } 7 } 8 }
Como essa fase do processo de desfragmentação contém várias operações, o valor do campo
remainingChunksToProcess
não mudará quando uma migração for concluída, mas a operaçãomergeChunk
não estiver concluída para o mesmo chunk.1 { 2 "balancerCompliant": false, 3 "firstComplianceViolation": "defragmentingChunks", 4 "details": { 5 "currentPhase": "mergeChunks", 6 "progress": { "remainingChunksToProcess": 1 } 7 } 8 }
Quando o processo estiver concluído, para uma collection balanceada, o documento retornará as seguintes informações.
1 { 2 "balancerCompliant" : true, 3 "ok" : 1, 4 "operationTime" : Timestamp(1583193238, 1), 5 "$clusterTime" : { 6 "clusterTime" : Timestamp(1583193238, 1), 7 "signature" : { 8 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), 9 "keyId" : NumberLong(0) 10 } 11 } 12 }
Observação: existe a possibilidade de que sua coleção não esteja balanceada no final da desfragmentação. O balanceador então entrará em ação e começará a migrar dados como faz regularmente.
- Quanto tempo leva a desfragmentação?
- A duração da desfragmentação variará dependendo do tamanho e do “fragmentation state” de uma collection, com collections maiores e mais fragmentadas demorando mais.
- A primeira fase da desfragmentação mescla partes no mesmo fragmento, oferecendo benefícios imediatos ao seu cluster. Aqui estão algumas estimativas do pior caso para o tempo para concluir a fase um da desfragmentação:
- Collection com 100,000 blocos - < 18 horas
- Collection com 1,000,000 chunks - < 6 dias
- O processo de desfragmentação completo envolve a movimentação de chunks entre shards onde as velocidades podem variar de acordo com os recursos disponíveis e o tamanho de chunk configurado do cluster. É difícil estimar quanto tempo levará para seu cluster concluir a desfragmentação.
- Posso usar a desfragmentação para apenas alterar o tamanho do meu bloco?
- Sim, basta executar o comando com
"defragmentCollection: false"
.
- Como faço para interromper uma desfragmentação contínua?
- Execute o seguinte comando:
1 db.adminCommand( 2 { 3 configureCollectionBalancing: "<database>.<collection>", 4 defragmentCollection: false 5 } 6 )
- Posso alterar o tamanho do meu chunk durante a desfragmentação?
- Sim, mas isso resultará em uma desfragmentação abaixo do ideal, pois o novo tamanho do chunk só será aplicado em fases futuras da operação.
- Como alternativa, você pode interromper uma desfragmentação em andamento executando o comando novamente com
"defragmentCollection: false"
. Em seguida, basta executar o comando com o novo tamanho do bloco e"defragmentCollection: true"
.
- O que acontece se eu executar a desfragmentação com um tamanho de chunk diferente em uma collection onde a desfragmentação já está em andamento?
- Não execute a desfragmentação com um tamanho de chunk diferente em uma collection que esteja sendo desfragmentada, pois isso faz com que o processo de desfragmentação utilize o novo valor na próxima fase do processo de desfragmentação, resultando em uma desfragmentação abaixo do ideal.
- Posso executar a desfragmentação em várias collection simultaneamente?
- Sim. No entanto, um fragmento só pode participar de uma migração por vez, ou seja, durante a segunda fase da desfragmentação, um fragmento só pode doar ou receber um pedaço por vez.
- Posso desfragmentar coleções em diferentes tamanhos de bloco?
- Sim, o tamanho do bloco é específico para uma coleção. Assim, diferentes collections podem ser configuradas para ter diferentes tamanhos de chunk, se desejado.
- Por que vejo um bloco de 1TB em meus fragmentos, mesmo que eu tenha definido o chunkSize para 256MB?
- No MongoDB 6.0, o cluster não particionará mais os dados, a menos que seja necessário para facilitar a migração.Portanto, os chunks podem exceder o
chunkSize
configurado. Esse comportamento reduz o número de chunks em um shard, o que, por sua vez, reduz o impacto das migrações em um cluster.
- O valor “true” para a chave DefragmentCollection de ConfigureCollectionBalancing é persistente depois de definido?
- A chave
defragmentCollection
só terá um valor de"true"
enquanto o processo de desfragmentação estiver ocorrendo. Quando o processo de desfragmentação terminar, o valor do campo desfragmentCollection será definido como verdadeiro.
- Como posso saber se a desfragmentação está sendo executada no momento, interrompida ou iniciada com êxito?
- Use o comandobalancerCollectionStatus para determinar o estado atual de desfragmentação em uma determinada collection.
- No documento retornado pelo comando
balancerCollectionStatus
, o campo firstComplianceViolation exibirá“defragmentingChunks”
quando uma collection estiver sendo desfragmentada ativamente. - Quando uma coleção não está sendo desfragmentada, o status do balanceador retorna um valor diferente para "firstComplianceViolation".
- Se a collection estiver desequilibrada, o comando retornará
“balancerCompliant: false”
e“firstComplianceViolation
:“chunksImbalance””
. - Se a coleção estiver balanceada, o comando retornará
“balancerCompliant: true”
. Consulte balancerCollectionStatus para obter mais informações sobre os outros valores possíveis.
- Como a desfragmentação afeta minha carga de trabalho?
- O impacto da desfragmentação em um cluster é semelhante a uma migração. As gravações serão bloqueadas na collection que está sendo desfragmentada enquanto as atualizações de metadados ocorrem em resposta às operações subjacentes de desfragmentação de mesclagem e movimentação. A duração do bloqueio de escrita pode ser estimada analisando os registros mongod de um shard de doador anterior.
- As leituras secundárias serão afetadas durante as operações de desfragmentação, pois as alterações no nó primário precisam ser replicadas para os secundários.
- Além disso, operações normais de balanceamento não ocorrerão para uma collection que está sendo desfragmentada.
- E se eu tiver uma janela de balanceamento?
- O processo de desfragmentação respeita as janelas de balanceamento e não executará nenhuma operação de desfragmentação fora da janela de balanceamento configurada.
- A desfragmentação é resiliente a falhas ou stepdowns?
- Sim, o processo de desfragmentação pode resistir a uma falha ou a uma queda primária. A desfragmentação será reiniciada automaticamente após a conclusão da atualização do novo primário.
- Existe uma maneira de simplesmente fazer a Fase Um da desfragmentação?
- No momento, você não pode, mas podemos adicionar esse recurso em um futuro próximo.
- E se eu ainda não estiver satisfeito com o número de chunks no meu cluster?
- Considere definir o tamanho do bloco para 1GB (1024MB) para desfragmentação a fim de mover mais blocos mescláveis.
1 db.adminCommand( 2 { 3 configureCollectionBalancing: "<database>.<collection>", 4 chunkSize: 1024, 5 defragmentCollection: true 6 } 7 )
- Como encontro o tamanho do chunk configurado do meu cluster?
- Você pode verificá-lo no banco de dados
“config”
.
1 use config 2 db.settings.find()
Observação: se o comando acima retornar Null, isso significa que o tamanho de bloco padrão do cluster não foi substituído e o tamanho de bloco padrão de 128MB está em uso no momento.
- Como encontro o tamanho do chunk de uma collection específica?
1 use <databasename> 2 db.adminCommand( 3 { 4 balancerCollectionStatus: "<database>.<collection>" 5 } 6 )
- Como encontro o número de chunks de uma collection específica?
1 use <databasename> 2 db.collection_name.getShardDistribution()