Com o mecanismo de armazenamento MMAPv1, as atualizações in-loco são frequentemente destacadas como uma estratégia de otimização porque os índices de um documento apontam diretamente para locais e deslocamentos de arquivos. Mover um documento para um novo local de armazenamento (especialmente se houver muitas entradas de índice para atualizar) tem mais sobrecarga para o MMAPv1 do que uma atualização in-loco que só precisa atualizar os campos alterados. Consulte:Características de armazenamento de registros em MMAPv1.
O WiredTiger não suporta atualizações in-loco porque internamente ele usa MVCC (Multiversion concurrency control), que é comumente usado por sistemas de gerenciamento de banco de dados. Essa é uma melhoria técnica significativa em relação à visão simplista do MMAP e permite a criação de recursos mais avançados, como níveis de isolamento e transações. Os índices do WiredTiger têm um nível de indireção (referenciando um RecordID interno em vez do local e deslocamento do arquivo), portanto, as movimentações de documentos no nível de armazenamento não são um ponto problemático significativo.
No entanto, este artigo também diz que "Mesmo que [WiredTiger] não permita atualizações in-loco, ele ainda pode ter um desempenho melhor que o MMAP para muitas cargas de trabalho".
Isso significa que, embora o MMAPv1 possa ter um caminho mais eficiente para atualizações in-loco, o WiredTiger tem outras vantagens, como compactação e controle de simultaneidade aprimorado. Talvez você possa construir uma carga de trabalho consistindo apenas de atualizações in-loco para alguns documentos que podem ter um desempenho melhor no MMAPv1, mas as cargas de trabalho reais são geralmente mais variadas. A única maneira de confirmar o impacto de uma determinada carga de trabalho seria testar em um ambiente representativo.
No entanto, a escolha geral de MMAPv1 vs WiredTiger é discutível se você quiser planejar o futuro:WiredTiger tem sido o mecanismo de armazenamento padrão desde o MongoDB 3.2 e alguns recursos de produtos mais recentes não são suportados pelo MMAPv1. Por exemplo, o MMAPv1 não suporta Majority Read Concern, o que, por sua vez, significa que não pode ser usado para Replica Set Config Servers (necessário para fragmentação no MongoDB 3.4+) ou Change Streams (MongoDB 3.6+). O MMAPv1 será preterido na próxima versão principal do MongoDB (4.0) e atualmente está programado para ser removido no MongoDB 4.2.
Quais são as implicações exatas das quais devo estar ciente quando uso o WiredTiger? Por exemplo, sem atualizações in-loco, o tamanho do banco de dados aumentará rapidamente?
Os resultados do armazenamento dependem de vários fatores, incluindo o design do esquema, a carga de trabalho, a configuração e a versão do servidor MongoDB. O MMAPv1 e o WiredTiger usam diferentes estratégias de alocação de registros, mas ambos tentarão usar o espaço pré-alocado marcado como livre/reutilizável. Em geral, o WiredTiger é mais eficiente com o uso do espaço de armazenamento e também tem a vantagem da compactação de dados e índices. O MMAPv1 aloca espaço de armazenamento adicional para tentar otimizar as atualizações in-loco e evitar movimentações de documentos, embora você possa escolher uma estratégia "sem preenchimento" para coleções em que a carga de trabalho não altera o tamanho do documento ao longo do tempo.
Houve um investimento significativo na melhoria e ajuste do WiredTiger para diferentes cargas de trabalho desde que foi introduzido pela primeira vez no MongoDB 3.0, portanto, recomendo fortemente o teste com a série de lançamentos de produção mais recente para obter o melhor resultado. Se você tiver uma pergunta específica sobre design de esquema e crescimento de armazenamento, sugiro postar detalhes no DBA StackExchange para discussão.
Também aprendi que o WiredTiger no MongoDB 3.6 adicionou a capacidade de armazenar deltas em vez de reescrever todo o documento (https://jira.mongodb.org/browse/DOCS-11416). O que isso significa, exatamente?
Este é um detalhe de implementação que melhora as estruturas de dados internas do WiredTiger para alguns casos de uso. Em particular, o WiredTiger no MongoDB 3.6+ pode ser mais eficiente ao trabalhar com pequenas alterações em documentos grandes (em comparação com versões anteriores). O cache do WiredTiger precisa ser capaz de retornar várias versões de documentos, desde que sejam usadas por sessões internas abertas (MVCC, conforme mencionado anteriormente), portanto, para documentos grandes com pequenas atualizações, pode ser mais eficiente armazenar uma lista de deltas. No entanto, se muitos deltas se acumularem (ou os deltas estiverem alterando a maioria dos campos em um documento), essa abordagem poderá ter menos desempenho do que manter várias cópias do documento completo.
Quando os dados são confirmados no disco por meio de um ponto de verificação, uma versão completa do documento ainda precisa ser gravada. Se você quiser saber mais sobre alguns dos componentes internos, há uma série de vídeos MongoDB Path To Transactions seguindo o desenvolvimento de recursos para suportar transações de vários documentos no MongoDB 4.0.
Além disso, o que eu não entendo é que hoje em dia a maioria (se não todos) os discos rígidos têm um tamanho de setor de 4096 bytes, então você não pode gravar no disco rígido apenas 4 bytes (por exemplo), mas deve escrever o bloco completo de 4096 bytes (então leia primeiro, atualize os 4 bytes nele e depois escreva). Como a maioria dos documentos geralmente tem <4096 bytes, isso significa que reescrever todo o documento é necessário em qualquer caso (mesmo com MMAP). O que eu perdi?
Sem entrar muito em detalhes de implementação e tentar explicar todas as partes móveis envolvidas, considere como as diferentes abordagens se aplicam a cargas de trabalho em que muitos documentos estão sendo atualizados (em vez de no nível de documento único), bem como o impacto no uso de memória (antes documentos são gravados em disco). Dependendo de fatores como tamanho e compactação do documento, um único bloco de E/S pode representar desde uma fração de um documento (tamanho máximo de 16 MB) até vários documentos.
No MongoDB, o fluxo geral é que os documentos são atualizados em uma visualização na memória (por exemplo, o cache do WiredTiger) com as alterações persistidas no disco em um formato de diário somente de acréscimo rápido antes de serem periodicamente liberados para os arquivos de dados. Se o sistema operacional precisar apenas gravar blocos de dados que foram alterados, tocar em menos blocos de dados exigirá menos E/S geral.