À medida que os bancos de dados NoSQL evoluíram, cada um deles adicionou APIs ou linguagens de nível superior para ajudar os programadores a fazer coisas complexas com facilidade. O SQL, tendo feito isso com os dados relacionais, mostrou o caminho. No SQL, os desenvolvedores dizem O QUE precisa ser feito e o mecanismo do banco de dados descobre COMO. HOW é o procedimento/algoritmo eficiente para executar a instrução. Selecionar, unir e projetar são as operações básicas de processamento do SQL. Mesmo em sistemas NoSQL, quando você modela os dados sem muita normalização, ainda é necessário unir uma coleção de objetos. Clientes com pedidos, pedidos com estoque, estoque com fornecedores, fornecedores com créditos e assim por diante. Por isso, o Couchbase N1QL oferece suporte a operações de união desde sua primeira versão. Depois disso, o MongoDB, na versão 3.2, adicionou o operador $lookup à estrutura de agregação para executar as operações de união.

Sem um recurso de consulta expressivo e de alto desempenho, os desenvolvedores de aplicativos precisam fazer isso dentro do aplicativo ou exportar os dados para um sistema que faça isso. Ambas as propostas são caras.

Neste artigo, compararemos o Couchbase com o MongoDB e suas diferentes abordagens para unir documentos JSON. Especificamente, faremos um estudo comparativo entre o uso de uniões para coleções do MongoDB e como podemos executá-las no Couchbase. As uniões não são compatíveis com o Cassandra CQL e o DynamoDB nativamente. Os desenvolvedores precisam fazer o trabalho por conta própria ou usar outras camadas, como Spark ou Amazon EMR, para obter o mesmo resultado. Portanto, não abordaremos esse assunto neste artigo.

Uniões no Couchbase

O Couchbase introduziu as uniões INNER e LEFT OUTER a partir do Couchbase 4.0 (2015). Isso oferece suporte a uniões em um relacionamento filho para pai. Documentos filhos (por exemplo, pedidos) podem ser unidos a documentos pais (por exemplo, cliente). Na versão 4.5 (2016), o Couchbase introduziu uniões de índices para consultar as uniões de pai para filho. Em ambos os casos, havia um valor de atributo implícito para o predicado de igualdade de chave de documento, especificado pela cláusula ON KEY.  

O Couchbase 5.5 tem SQL padrão ANSI estendido para JSON. Ele suporta INNER JOIN, LEFT OUTER JOIN e RIGHT OUTER join limitado. Usaremos exemplos baseados no Couchbase 5.5.

A documentação do Couchbase se une: https://developer.couchbase.com/documentation/server/5.5/n1ql/n1ql-language-reference/from.html

Uniões e coleções do MongoDB:

As uniões são compatíveis com o operador $lookup dentro da estrutura de agregação.

Veja a seguir trechos da documentação do MongoDB.

Novo na versão 3.2.

Executa uma junção externa esquerda com uma coleção não fragmentada no mesmo para filtrar os documentos da coleção "unida" para processamento. Para cada documento de entrada, o $lookup adiciona um novo campo de matriz cujos elementos são os documentos correspondentes da coleção "joined". A etapa $lookup passa esses documentos reformulados para o próximo estágio.

Eliot Horowitz, CTO do MongoDB, disse: "A agregação do MongoDB é semelhante ao pipeline do Unix. A saída de um estágio vai para outro.... [é] muito processual. Permite que você pense de uma forma muito processual."

MongoDB $lookup : https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/


Interessado em saber mais sobre JOINs? Leia o artigo de Lukas Eder. https://dzone.com/articles/a-probably-incomplete-comprehensive-guide-to-the-many-different-ways-to-join-tables-in-sql


Comparação de alto nível entre o Couchbase N1Ql e o MongoDB.

Couchbase N1QL: Oferece suporte a INNER JOIN, LEFT OUTER JOIN e RIGHT OUTER JOIN limitado. A linguagem de consulta, como o SQL, é declarativa. Os desenvolvedores escrevem e as ferramentas geram a consulta de acordo com a sintaxe N1QL. O mecanismo descobre o plano e executa a consulta.

MongoDB: oferece suporte a LEFT OUTER JOIN somente para valores escalares. O design das junções na linguagem de consulta do MongoDB é feito para ajudar a escrever a consulta e processar os dados de forma processual. 

Implicações:

  1. O conjunto de resultados da união externa esquerda é um superconjunto do conjunto de resultados da união interna. É possível acrescentar predicados adicionais para eliminar os documentos não correspondentes (com projeção nula ou lado subserviente ausente da união) depois que a união externa esquerda for executada. Isso é como ir de São Francisco a Chicago via Londres. Você pode fazer isso, mas é caro. Para a execução da consulta, são necessários tempo, memória e recursos de CPU que afetam o desempenho geral do sistema.
  2. O suporte do N1QL para junções é declarativo. A linguagem do MongoDB é um tanto processual. Você precisa separar os predicados, pensar na ordem de junção entre as coleções, pensar em quando agrupar, classificar, etc. Escrever consultas com agregação do MongoDB é como escrever planos de consulta, passo a passo.

Exemplos:

Usamos o modelo e os dados simples de amostra de viagem. Aqui estão os detalhes dos dados do modelo. https://developer.couchbase.com/documentation/server/4.5/travel-app/travel-app-data-model.html

Simplesmente exportamos os dados do Couchbase e os importamos para um banco de dados Mongo chamado travel-sample. No MongoDB, os 5 tipos diferentes de documento (ponto de referência, rota, companhia aérea, aeroporto, hotel) são armazenados em 5 coleções com seus respectivos nomes.

Exemplo 1: LEFT OUTER JOIN com a cláusula ON em valores escalares.

Couchbase N1QL

Consulta ao MongoDB

Observações:

Essa é uma consulta de união externa à esquerda bastante simples que une duas coleções e, em seguida, simplesmente conta o número total de documentos produzidos. Observe que, diferentemente do N1QL (e do SQL), no MongoDB, você ainda precisa agrupar o conjunto de resultados para obter a contagem, mesmo que tenha um único grupo.

Exemplo 2: Liste os aeroportos e pontos de referência na mesma cidade, ordenados pelos aeroportos.

Couchbase N1QL:

MongoDB:

Observações:

  1. Essa consulta usa INNER JOIN, que o MongoDB não tem. Portanto, no MongoDB, você primeiro faz a junção de pesquisa para obter o LEFT OUTER JOIN e, em seguida, elimina documentos não correspondentes, mas projetados (por causa do left outer) usando o estágio de correspondência (código: $match: {"airline_docs": {$ne: []}}).
  2. Em seguida, lembre-se de que os documentos correspondentes estão em uma estrutura de dados de matriz, desenrole-os antes de agrupá-los pelo landmark.name. Em seguida, faça a classificação e a projeção final.

Como esperado, a consulta de junção do MongoDB é processual e você precisa entender o plano de execução e escrever o código para cada estágio.

Exemplo 3: partindo de São Francisco, encontre todos os aeroportos de destino (aqueles que têm rotas a partir de SFO).

Couchbase N1QL

MongoDB:

Observações:

  1. A cláusula de união para essa consulta é um pouco mais complexa, com dois predicados (airport.faa = (route.sourceairport AND route.type = "route"). Isso requer uma sintaxe de pipeline complicada na consulta do MongoDB.
  2. E como você precisa diferenciar as duas coleções, é necessário outro estágio do let para criar as variáveis locais para os atributos do aeroporto.
  3. Como antes, é necessária uma cláusula de correspondência adicional para eliminar documentos de companhias aéreas sem correspondência (vazios), seguida de agrupamento e classificação.
  4. Como você pode ver visualmente, a consulta do MongoDB está ficando cada vez maior para fazer o mesmo trabalho que o N1QL do Couchbase.

Exemplo 4: Encontre todos os hotéis e pontos de referência em Yosemite. Os hotéis devem ter mínimo 5 curtidas.

Couchbase N1QL

MongoDB:

Observação:

  1. Traduzir o predicado LIKE em uma expressão regular foi simples, mas determinar se havia pelo menos cinco public_likes não foi. Foi necessária uma fase adicional de projeção e correspondência para calcular o tamanho dos public_likes no final.
  2. Quando você tem muitos atributos para combinar, manipular e projetar, é necessário renomeá-los adequadamente no estágio apropriado, caso contrário, a consulta não poderá fazer referência a eles. Por exemplo, hotel.name teve de ser renomeado para hname antes do desenrolar. Talvez haja uma maneira melhor de escrever esse estágio!
  3. O N1QL expressou a consulta em 370 caracteres. O MongoDB exigiu 956 caracteres. Tudo isso para uma junção de duas tabelas. À medida que a complexidade aumenta, a proporção também aumenta, pois a consulta do MongoDB é escrita de forma processual.

Exemplo 5: Encontre todos os hotéis e pontos de referência em Yosemite. Os hotéis devem ter pelo menos 5 curtidas.

Esse exemplo é igual ao Exemplo 4, mas mais rápido!

Couchbase N1QL

Observação:

O método de junção padrão no Couchbase N1QL é a junção de loop aninhado. Isso funciona bem quando você tem um número menor de documentos envolvidos em cada lado da união. Quando você tem um conjunto de dados maior, normalmente em consultas de relatórios, a junção de loop aninhado fica mais lenta. O Couchbase N1QL tem junções de hash e isso acelera significativamente as junções. Quando cada lado da união tem de milhares a milhões de documentos, o aumento de velocidade pode ser de 2x a 20x ou mais. Veja a seção blog detalhado do Couchbase sobre junções ANSI para obter mais informações.

Com base na documentação e no plano de explicação, não está claro qual método de junção o MongoDB usa. Alguns blogs indicam que eles usaram uma junção de loop aninhado para implementar o operador $lookup.

Resumo:

 

Couchbase N1QL MongoDB
Abordagem JOIN Declarativo, como o SQL.

Permite a união entre conjuntos de dados distribuídos e de qualquer tamanho.

Procedimental com alguns aspectos declarativos (por exemplo, seleção de índices).

Só é possível ingressar em uma coleção fragmentada em um coleção não fragmentada. Para unir duas coleções fragmentadas, os aplicativos terão que escrever o algoritmo de união.

JOINs suportados UNIÃO EXTERNA ESQUERDA

INNER JOIN

UNIÃO EXTERNA DIREITA

O $lookup implementa o LEFT OUTER JOIN em valores escalares.
Suporte à cláusula ON Expressões completas.

Cicatrizes

Matrizes

Igualdade implícita

Expressão do pipeline

As matrizes devem ser $unwind antes do $lookup

Implementação do JOIN Bloqueio de loop aninhado

Junção de hash com construção e sondas definidas pelo usuário.

Loop aninhado
Cláusula ON ON com qualquer expressão. 1TP4Expressão de linha de produção
Expressões de matriz na cláusula ON Use expressões ANY, IN.

Suporta UNNEST

Pipeline com $unwind antes de $match
Explicar Explicação visual e

Explicação JSON

Explicação visual e

Explicação JSON

JOIN order Da esquerda para a direita, conforme especificado pelo usuário. O otimizador é baseado em regras. Conforme especificado no pipeline.
JOINs aninhados Suportado por meio de tabelas derivadas.

A cláusula FROM pode ter subseleções que, por sua vez, podem ter uniões ou subseleções.

Não
Processamento do predicado JOIN O otimizador processa os predicados de união, os predicados constantes e os envia automaticamente para o índice. Projeto manual de predicados para cada coleção, ordenação cuidadosa dos estágios do pipeline sem a ajuda total do otimizador.

E quanto ao desempenho? Boa pergunta. Isso é para um blog futuro!

E agora, uma citação:

"Uma frase não deve conter palavras desnecessárias, um parágrafo não deve conter frases desnecessárias, pelo mesmo motivo que um desenho não deve ter linhas desnecessárias e uma máquina não deve ter peças desnecessárias."

- William Strunk, Jr.  Elementos de estilo.

Referências:

  1. Documentação do Couchbase: https://docs.couchbase.com
  2. Documentação do MongoDB: https://docs.mongodb.com/
  3. Uniões ANSI no Couchbase N1QL: https://www.couchbase.com/blog/ansi-join-support-n1ql/
  4. Tutorial N1QL: https://query-tutorial.couchbase.com/tutorial/#1

Autor

Postado por Keshav Murthy

Keshav Murthy é vice-presidente de P&D da Couchbase. Anteriormente, ele trabalhou na MapR, IBM, Informix e Sybase, com mais de 20 anos de experiência em design e desenvolvimento de bancos de dados. Ele liderou a equipe de P&D de SQL e NoSQL na IBM Informix. Recebeu dois prêmios President's Club na Couchbase e dois Outstanding Technical Achievement Awards na IBM. Keshav é bacharel em Ciência da Computação e Engenharia pela Universidade de Mysore, Índia, detém dez patentes nos EUA e tem três patentes pendentes nos EUA.

Deixar uma resposta