MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

MongoDB (noSQL) quando dividir coleções


Como já foi escrito, não existem regras como a segunda forma normal para SQL.

No entanto, existem algumas práticas recomendadas e armadilhas comuns relacionadas à otimização para o MongoDB que listarei aqui.

Uso excessivo de incorporação

O limite de BSON


Ao contrário da crença popular, não há nada de errado com referências. Suponha que você tenha uma biblioteca de livros e queira acompanhar os aluguéis. Você poderia começar com um modelo como este
{
  // We use ISBN for its uniqueness 
  _id: "9783453031456"
  title: "Schismatrix",
  author: "Bruce Sterling",
  rentals: [
    {
      name:"Markus Mahlberg,
      start:"2015-05-05T03:22:00Z",
      due:"2015-05-12T12:00:00Z"
    }
  ]
}

Embora existam vários problemas com este modelo, o mais importante não é óbvio – haverá um número limitado de aluguéis devido ao fato de que os documentos BSON têm um limite de tamanho de 16 MB.

O problema de migração de documentos


O outro problema com o armazenamento de aluguéis em uma matriz seria que isso causaria migrações de documentos relativamente frequentes, o que é uma operação bastante cara. Os documentos BSON nunca são particionados e criados com algum espaço adicional alocado antecipadamente usado quando crescem. Esse espaço adicional é chamado de preenchimento. Quando o preenchimento é excedido, o documento é movido para outro local nos arquivos de dados e um novo espaço de preenchimento é alocado. Portanto, adições frequentes de dados causam migrações frequentes de documentos. Portanto, é uma prática recomendada evitar atualizações frequentes aumentando o tamanho do documento e usar referências.

Então, para o exemplo, mudaríamos nosso modelo único e criaríamos um segundo. Primeiro, o modelo para o livro
{
  _id: "9783453031456",
  title:"Schismatrix",
  author: "Bruce Sterling"
}

O segundo modelo para locação ficaria assim
{
  _id: new ObjectId(),
  book: "9783453031456",
  rentee: "Markus Mahlberg",
  start: ISODate("2015-05-05T03:22:00Z"),
  due: ISODate("2015-05-05T12:00:00Z"),
  returned: ISODate("2015-05-05T11:59:59.999Z")
}

A mesma abordagem, é claro, poderia ser usada para autor ou locatário.

O problema da normalização excessiva


Vamos olhar para trás algum tempo. Um desenvolvedor identificaria as entidades envolvidas em um caso de negócios, definiria suas propriedades e relações, escreveria as classes de entidade correspondentes, bateria a cabeça contra a parede por algumas horas para obter o trabalho triplo interno-externo-acima-e-além do JOIN necessário para o caso de uso e todos viveram felizes para sempre. Então, por que usar NoSQL em geral e MongoDB em particular? Porque ninguém viveu feliz para sempre. Essa abordagem escala horrivelmente e quase exclusivamente a única maneira de escalar é vertical.

Mas a principal diferença do NoSQL é que você modela seus dados de acordo com as perguntas que precisam ser respondidas.

Dito isto, vamos olhar para uma relação n:m típica e tomar a relação de autores para livros como nosso exemplo. Em SQL, você teria 3 tabelas:duas para suas entidades (livros e autores ) e um para a relação (Quem é o autor de qual livro? ). Claro, você pode pegar essas tabelas e criar suas coleções equivalentes. Mas, como não há JOINs no MongoDB, você precisaria de três consultas (uma para a primeira entidade, uma para suas relações e outra para as entidades relacionadas) para encontrar os documentos relacionados de uma entidade. Isso não faria sentido, já que a abordagem de três tabelas para relações n:m foi inventada especificamente para superar os esquemas rígidos que os bancos de dados SQL impõem. Como o MongoDB tem um esquema flexível, a primeira questão seria onde armazenar a relação, mantendo os problemas decorrentes do uso excessivo de incorporação em mente. Como um autor pode escrever vários livros nos próximos anos, mas a autoria de um livro raramente muda, a resposta é simples:armazenamos os autores como uma referência aos autores nos dados dos livros
{
  _id: "9783453526723",
  title: "The Difference Engine",
  authors: ["idOfBruceSterling","idOfWilliamGibson"]
}

E agora podemos encontrar os autores desse livro fazendo duas consultas:
var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})

Espero que o acima o ajude a decidir quando realmente "dividir" suas coleções e contornar as armadilhas mais comuns.

Conclusão


Quanto às suas perguntas, aqui estão minhas respostas
  1. Como escrito antes:Não , mas manter as limitações técnicas em mente deve dar uma ideia de quando isso pode fazer sentido.
  2. Não é ruim – desde que se adeque ao(s) seu(s) caso(s) de uso . Se você tiver uma determinada categoria e seu _id , é fácil encontrar os produtos relacionados. Ao carregar o produto, você pode obter facilmente as categorias a que pertence, de forma ainda mais eficiente, como _id é indexado por padrão.
  3. Ainda não encontrei um caso de uso que não possa ser feito com o MongoDB, embora algumas coisas possam ficar um pouco mais complicadas com o MongoDB. O que você deve fazer é pegar a soma de seus requisitos funcionais e não funcionais e verificar se as vantagens superam as desvantagens. Minha regra geral:se um de "escalabilidade" ou "alta disponibilidade/failover automático" estiver na sua lista de requisitos, o MongoDB vale mais do que uma olhada.