Melhores Práticas para Gerenciar e Reduzir o Uso de Espaço em Disco no MongoDB
Otimize o uso de disco do MongoDB com este guia abrangente de melhores práticas. Aprenda estratégias eficazes para compactar coleções e índices, identificar e remover índices desnecessários e aproveitar os recursos de compressão do WiredTiger. Descubra como implementar arquivamento de dados, gerenciar o tamanho do oplog e monitorar proativamente o espaço em disco para evitar interrupções no sistema e melhorar o desempenho. Este artigo fornece insights acionáveis e exemplos práticos para manter suas implantações MongoDB enxutas e eficientes.
Melhores Práticas para Gerenciar e Reduzir o Uso de Espaço em Disco no MongoDB
O uso de disco do MongoDB geralmente se torna urgente no pior momento possível: um job em lote executa por mais tempo que o esperado, exclusões não parecem liberar espaço, ou um membro de um conjunto de réplicas começa a alertar que o volume está quase cheio. A correção raramente é um único comando mágico. Você precisa saber se o espaço é de dados ativos, índices, espaço reutilizável do WiredTiger, oplog, logs ou backups locais.
A abordagem mais segura é medir primeiro, reduzir o que não precisa mais existir e só então executar manutenção mais pesada, como compactação ou reconstrução de membros. Essa ordem evita que você crie um longo evento de manutenção que devolve pouco espaço.
Entendendo o Consumo de Espaço em Disco do MongoDB
O MongoDB utiliza espaço em disco para vários componentes:
- Arquivos de Dados: Armazena os documentos BSON reais dentro das coleções.
- Arquivos de Índice: Armazena índices B-tree criados para suportar a execução eficiente de consultas.
- Arquivos de Journal (WiredTiger): Registra operações de escrita antes de serem aplicadas aos arquivos de dados, garantindo a durabilidade dos dados. Estes são pré-alocados.
- Oplog (Log Operacional): Uma coleção limitada especial em conjuntos de réplicas que registra todas as operações de escrita. Essencial para replicação.
- Dados de Diagnóstico: Logs, arquivos de processo
mongode outras informações relacionadas ao sistema.
Com o tempo, devido a atualizações, exclusões e crescimento de documentos (padding), coleções e índices podem se tornar fragmentados ou conter espaço alocado não utilizado, levando a um uso ineficiente do disco. Este "espaço branco" não é imediatamente recuperado pelo sistema operacional, mesmo que o banco de dados não precise mais dele para dados ativos.
Estratégias para Reduzir o Espaço em Disco do MongoDB
1. Compactando Coleções e Índices
Operações de compactação ajudam a recuperar espaço em disco não utilizado, reescrevendo arquivos de dados e índices de forma mais eficiente. Isso pode ser particularmente útil após exclusões ou atualizações significativas de dados.
Compactando Coleções
Com o mecanismo de armazenamento WiredTiger (padrão desde o MongoDB 3.2), compact recupera principalmente espaço livre de documentos excluídos e desfragmenta coleções. Ele não reconstrói o arquivo de dados da coleção do zero como a operação compact do MMAPv1 fazia.
db.runCommand({ compact: "myCollection" })
Considerações sobre compact:
- Operações
compactpodem consumir muitos recursos (CPU, I/O) e levar um tempo significativo, especialmente para coleções grandes. Geralmente é melhor executá-las durante janelas de manutenção ou em membros secundários de um conjunto de réplicas. - Os requisitos de disco e o comportamento de bloqueio variam de acordo com a versão do MongoDB, o mecanismo de armazenamento e a forma de implantação. Verifique a documentação para sua versão exata antes de executá-lo em uma coleção de produção grande.
- Para clusters fragmentados, execute
compactem cada fragmento de forma independente.
Reconstruindo Índices
Os índices também podem se tornar fragmentados. Reconstruir um índice pode recuperar espaço e potencialmente melhorar o desempenho de consultas.
db.myCollection.reIndex()
Considerações sobre reIndex():
- O comportamento de
reIndex()mudou entre as versões do MongoDB e ainda pode ser disruptivo em sistemas ocupados. Verifique o manual para sua versão, teste em staging e prefira trabalhar de forma gradual através dos membros do conjunto de réplicas quando possível. - Semelhante ao
compact,reIndex()requer espaço em disco adicional durante a operação.
repairDatabase (Operação Offline)
Para fragmentação severa ou corrupção de dados, repairDatabase pode reconstruir todos os arquivos de dados. Esta é uma operação offline e requer a parada da instância mongod.
mongod --repair
Aviso: repairDatabase deve ser usado como último recurso para recuperação de espaço, pois é uma operação destrutiva se não for tratada com cuidado e pode levar muito tempo. Sempre tenha um backup.
2. Otimizando Índices
Os índices são cruciais para o desempenho, mas podem consumir espaço significativo em disco. Índices não utilizados ou redundantes são pura sobrecarga.
Identificando e Removendo Índices Desnecessários
Revise regularmente seus índices para garantir que ainda são necessários.
- Liste todos os índices de uma coleção:
db.myCollection.getIndexes()
```
2. Monitore o uso do índice: Use $indexStats, planos de consulta, profiling e o histórico de carga de trabalho da sua aplicação. As estatísticas da coleção mostram o tamanho do índice, mas não provam se um índice é útil.
3. Identifique índices duplicados ou redundantes: Por exemplo, um índice em { a: 1, b: 1 } torna um índice em { a: 1 } redundante para consultas que podem usar o índice composto. Um índice em { a: 1, b: 1 } também é coberto por um índice em { a: 1, b: 1, c: 1 } para consultas que envolvem apenas a e b.
Uma vez identificado, remova o índice não utilizado:
db.myCollection.dropIndex("indexName")
Dica: Sempre teste o impacto de remover um índice em um ambiente de staging antes de aplicá-lo à produção.
Usando Índices Parciais
Índices parciais indexam apenas documentos em uma coleção que satisfazem uma expressão de filtro especificada. Isso reduz o número de documentos indexados, economizando espaço em disco e melhorando o desempenho de escrita.
db.orders.createIndex(
{ customerId: 1, orderDate: -1 },
{ partialFilterExpression: { status: "active" } }
)
Este índice incluiria apenas documentos onde status é "active", reduzindo seu tamanho se a maioria dos pedidos for histórica, cancelada, arquivada ou estiver fora do caminho crítico. A parte importante não é a palavra "active"; é o hábito de indexar o subconjunto que sua aplicação realmente consulta todos os dias.
Comece com uma Triagem de Espaço em Disco, Não com um Comando de Limpeza
Quando o espaço em disco do MongoDB está crescendo, o primeiro erro é pular direto para compact, repair ou excluir dados antigos. Essas ações podem ajudar, mas também podem criar carga, travar em algumas situações ou esconder o problema real por algumas semanas. Comece respondendo a três perguntas:
- Qual sistema de arquivos está enchendo: o caminho do banco de dados, o caminho do journal, o caminho do log ou o volume de backup?
- Os dados ativos estão crescendo, ou o espaço alocado mas não utilizado está crescendo após exclusões e atualizações?
- O crescimento vem de coleções, índices, oplog, logs, dados de diagnóstico ou snapshots?
Uma primeira passagem rápida geralmente se parece com isso:
df -h
du -h --max-depth=1 /var/lib/mongodb | sort -h
du -h --max-depth=1 /var/log/mongodb | sort -h
Em seguida, verifique o MongoDB a partir do shell:
db.adminCommand({ listDatabases: 1 })
db.getSiblingDB("app").stats()
db.getSiblingDB("app").orders.stats()
storageSize, totalIndexSize e dataSize contam histórias diferentes. Se dataSize está crescendo, você provavelmente tem um problema de ciclo de vida dos dados. Se storageSize é muito maior que dataSize, você pode estar olhando para espaço interno reutilizável após exclusões. Se totalIndexSize é grande em comparação com dataSize, o design do índice merece atenção antes de você tocar na compactação.
Entenda o que o MongoDB Pode e Não Pode Devolver
Com o WiredTiger, excluir documentos geralmente torna o espaço disponível para reutilização pelo MongoDB. Isso nem sempre devolve esse espaço ao sistema operacional imediatamente. Esse comportamento surpreende as pessoas durante a limpeza de emergência: elas excluem um grande lote, executam df -h e veem quase nenhuma melhoria.
Isso não significa que a exclusão falhou. Significa que o MongoDB muitas vezes pode reutilizar esse espaço para futuras inserções e atualizações. Se o objetivo é parar o crescimento, excluir ou arquivar dados antigos pode ser suficiente. Se o objetivo é encolher o sistema de arquivos porque o volume está quase cheio ou o host está sendo reduzido, você pode precisar de compactação, ressincronização de um membro do conjunto de réplicas ou uma reconstrução do tipo dump-and-restore.
Para sistemas de produção, geralmente separo o trabalho em duas trilhas. A primeira trilha é a segurança imediata: adicionar disco, remover acúmulo óbvio de logs, pausar jobs em lote arriscados ou mover backups para fora do volume do banco de dados. A segunda trilha é a redução real: corrigir retenção, remover índices não utilizados e reconstruir o armazenamento somente depois de saber para onde os bytes foram.
Corrija a Retenção de Dados Antes de Desfragmentar Qualquer Coisa
Se sua aplicação mantém logs de requisição, eventos, sessões, notificações, registros de jobs ou documentos de análise para sempre, o uso do disco retornará, não importa o quão cuidadosamente você compacte. O MongoDB oferece algumas opções práticas.
Para dados que expiram em um timestamp simples, um índice TTL é geralmente a resposta mais limpa:
db.sessions.createIndex(
{ expiresAt: 1 },
{ expireAfterSeconds: 0 }
)
Esse índice remove documentos após a data armazenada em expiresAt. É útil para sessões, tokens temporários, jobs de importação de curta duração ou respostas de API em cache. Não é um substituto para regras de retenção de negócios. O monitor TTL é executado em segundo plano, portanto, não espere exclusão segundo a segundo e não use TTL em dados que exigem um fluxo de trabalho de aprovação antes da exclusão.
Para registros de negócios, arquive em vez de excluir cegamente. Um padrão comum é:
- Copiar documentos mais antigos que a janela de retenção para armazenamento mais barato ou um banco de dados de arquivo.
- Verificar contagens e uma amostra de campos importantes.
- Excluir em pequenos lotes da coleção primária.
- Observar o lag de replicação e as métricas de disco enquanto o job é executado.
Lotes pequenos são importantes. Uma única exclusão enorme pode criar pressão de replicação, encher logs e tornar o rollback mais difícil se alguém perceber que o filtro estava errado. Um job em lote mais seguro pode excluir alguns milhares de documentos de cada vez, dormir brevemente e registrar o progresso por _id ou timestamp.
while (true) {
const result = db.events.deleteMany({
createdAt: { $lt: ISODate("2025-01-01T00:00:00Z") },
archived: true
});
print(`deleted ${result.deletedCount}`);
if (result.deletedCount === 0) break;
sleep(500);
}
Em um script de produção real, adicione um padrão de limite em vez de deleteMany em todo o intervalo, registre cada lote e pare automaticamente se o lag de replicação ou I/O de disco ultrapassar seu limite.
Cuidado com Conselhos de Índice que Parecem Muito Simples
Remover índices não utilizados é uma das melhores maneiras de reduzir o espaço em disco do MongoDB, mas "não utilizado" precisa de contexto. Um índice pode parecer não utilizado durante uma semana tranquila e ainda ser crítico para relatórios de fim de mês, reconciliação em segundo plano ou um fluxo de trabalho raro de suporte ao cliente.
Use $indexStats para ver padrões de acesso:
db.orders.aggregate([{ $indexStats: {} }])
Em seguida, compare o resultado com o código da aplicação, jobs agendados, dashboards e consultas de suporte. Se um índice não foi usado desde a última reinicialização, isso é um sinal, não um veredito. Antes de removê-lo, verifique se o servidor foi reiniciado recentemente e se a amostra de carga de trabalho inclui os jobs que importam.
Também fique atento a índices compostos sobrepostos. Se você tem estes:
{ customerId: 1 }
{ customerId: 1, createdAt: -1 }
{ customerId: 1, createdAt: -1, status: 1 }
você pode ser capaz de remover um, mas apenas depois de verificar a ordem de classificação, os filtros de consulta e se o índice mais curto suporta um padrão de acesso diferente. O MongoDB pode usar o prefixo esquerdo de um índice composto, mas isso não significa que o maior índice é sempre um substituto gratuito. Índices maiores custam mais memória e I/O de escrita, portanto, mantenha aquele que se adequa à carga de trabalho, não o que parece mais completo.
Prefira Ressincronização para Grandes Operações de Redução em Conjuntos de Réplicas
Para um conjunto de réplicas grande, a maneira mais limpa de recuperar espaço em disco do sistema operacional é muitas vezes reconstruir um secundário de cada vez. A ideia básica é:
- Confirmar que você tem replicação saudável e backups atuais.
- Remover ou parar um secundário.
- Limpar seu diretório de dados local.
- Deixá-lo ressincronizar a partir do primário ou de outro membro saudável.
- Repetir para o próximo secundário.
- Rebaixar o primário durante uma janela de manutenção e reconstruir o antigo primário por último.
Esta abordagem é mais lenta do que executar um comando, mas é mais fácil de raciocinar porque cada membro reconstruído escreve novos arquivos de armazenamento com base nos dados atuais. Também evita tentar compactar todas as coleções sob tráfego de produção. Não é gratuita: a sincronização inicial pode ser pesada em rede e disco, e você precisa de membros restantes suficientes para manter o conjunto de réplicas seguro enquanto um membro está sendo reconstruído.
Para um servidor MongoDB independente, você não tem esse luxo. Nesse caso, planeje uma janela de manutenção, faça um backup testado e considere mongodump/mongorestore ou migração em nível de sistema de arquivos para um novo volume. Não escolha mongod --repair só porque você quer um diretório de dados menor. Trate o repair como uma ferramenta de recuperação, não como manutenção de rotina.
Fique de Olho no Oplog, Logs e Backups Também
Nem toda pressão de disco do MongoDB vem das coleções. Em conjuntos de réplicas, o oplog é uma coleção limitada, portanto, não deve crescer para sempre, mas seu tamanho configurado ainda importa. Se for muito pequeno, os secundários podem ficar para trás durante a manutenção. Se for muito maior do que o necessário em um disco pequeno, pode estar desperdiçando espaço. Revise-o deliberadamente:
db.getSiblingDB("local").oplog.rs.stats()
Os logs do MongoDB também podem encher um disco quando o log de consultas lentas, a verbosidade de depuração ou um loop de erro de aplicação se torna ruidoso. Use rotação de logs e mantenha os logs do banco de dados longe do mesmo volume pequeno que armazena dados, sempre que possível.
Backups são outra surpresa comum. As equipes às vezes executam mongodump no mesmo host porque é conveniente, e depois se perguntam por que os alertas de disco disparam durante a janela de backup. Um backup armazenado no mesmo sistema de arquivos não é um grande backup e pode empurrar o MongoDB para uma interrupção pior durante uma operação já arriscada. Transmita backups para armazenamento de objetos, um servidor de backup ou um volume montado separado.
Um Runbook Prático para um Disco Cheio do MongoDB
Se o disco já está acima de 90%, vá devagar e trabalhe nesta ordem:
- Confirme se o MongoDB ainda está aceitando escritas e se o conjunto de réplicas está saudável.
- Adicione capacidade de disco temporária se a plataforma permitir. Isso geralmente é mais seguro do que exclusão de emergência.
- Mova ou rotacione logs excessivamente grandes e arquivos de backup locais.
- Pare jobs em lote não essenciais que estão escrevendo intensamente.
- Identifique as maiores coleções e índices com
db.stats()estats()de coleção. - Arquive ou exclua apenas dados com uma regra de retenção clara.
- Planeje compactação, ressincronização ou restauração depois que o sistema estiver estável.
A melhor correção de longo prazo é chata: regras de retenção, revisões de índice, alertas de disco e procedimentos de reconstrução testados. O MongoDB é confortável em reutilizar espaço livre interno, mas os operadores ainda precisam decidir quais dados merecem viver em armazenamento rápido e o que pode ser movido para outro lugar.