O SQL existe há muuuuito tempo. É uma maneira muito intuitiva e eficiente de processar dados estruturados e tem sido a escolha para bancos de dados há muitos anos. No entanto, com o mundo dos BIG DATA, os dados velocidade, variedade e volume. O SQL pode enfrentar os 2 "v" está bem com as otimizações: "velocidade" e "volume". Na verdade, muitos dos novos dialetos do SQL (N1QL, Spark, U-SQL, Impala, Drill e outros) estão fazendo exatamente isso. No entanto, "variedade" é um jogo diferente! O Big Data é complexo no novo mundo; ele tem um esquema imprevisível, em constante evolução e irregular, valores esparsos e estruturas profundamente aninhadas. Para isso, o SQL precisa ser ampliado!
Bem, estou muito animado em informar que criamos o N1QL no Couchbase Server 4 para resolver exatamente esses problemas! O N1QL pode percorrer facilmente as estruturas complexas do JSON (o padrão de serialização de fato para dados complexos). Usando o N1QL, você pode trabalhar não apenas com NULLs, mas também com atributos que são FALTANDO em vários formatos de JSON que você processa. OU você pode usar operadores como QUALQUER/TODO para consultar matrizes incorporadas no documento JSON. OU você pode usar comandos como UNNEST E NEST que pode achatar ou desaninhar matrizes aninhadas. Há muitas dessas extensões poderosas para serem contadas aqui, portanto, não farei isso. Em vez disso, vou mostrar uma joia oculta que foi publicada originalmente aqui por Gerald. Essa gema é muito útil com agregados se você estiver usando o N1QL em comparação com um banco de dados relacional como o SQL Server.
Uma das grandes vantagens do N1QL é sua capacidade de entender os tipos de matriz. Funções de agregação como MAX() não são revolucionárias, mas com as adições de aninhamento e matrizes, algo tão simples como MAX() pode ser superpoderoso. Uma observação antes de me aprofundar: vou escolher o TSQL e o SQL Server porque contribuí para o TSQL em minha vida anterior na Microsoft. No entanto, isso também se aplica ao Oracle, Postgres, Mysql, Informix ou DB2 e muito mais... Ok, então: Imagine tentar encontrar os atributos do produto que tem o preço MÁXIMO. No SQL Server, essa é uma consulta bastante simples de escrever usando TSQL;
|
1 2 3 |
SELECIONAR ID do produto, nome DE t1 ONDE preço = (SELECIONAR MAX(preço) DE t1) IR |
Isso é bom. Aqui está o resultado - o produto com o preço mais alto é o produto chamado "c" com ID 3.
|
1 2 3 4 |
ID do produto nome ----------- ----------------------------------------------------------------- 3 c |
Esta é a aparência do plano de execução. Basicamente, o plano de execução procura o valor do preço MAX. Uma vez que você tenha o valor, é uma junção de loop aninhado para pesquisar os outros atributos do produto na tabela, como productID e name.
|
1 2 3 4 5 6 7 8 |
Declaração Texto --------------------------------------------------------------------------------------------- selecionar ID do produto, nome de t1 onde preço = (selecionar máximo(preço) de t1) |--Aninhado Laços(Interno Aderir, ONDE:([Expr1004]=[teste].[dbo].[t1].[preço])) |--Fluxo Agregado(DEFINIR:([Expr1004]=MAX([teste].[dbo].[t1].[preço]))) | |--Agrupados Índice Escaneamento(OBJETO:([teste].[dbo].[t1].[PK__t1__2D10D14A7FD17868])) |--Agrupados Índice Escaneamento(OBJETO:([teste].[dbo].[t1].[PK__t1__2D10D14A7FD17868])) |
No entanto, o N1QL tem uma grande vantagem aqui. Como ele pode processar MAX() com matrizes, você pode retornar todos os atributos do documento sem uma verificação adicional.
|
1 |
SELECIONAR MAX([preço, {ID do produto, nome]) DE teste; |
OU você pode simplesmente retornar o documento completo usando a seguinte consulta;
|
1 |
SELECIONAR MAX([preço, teste]) DE teste; |
Vamos dar uma olhada no plano de execução da consulta N1QL. Aqui vem o spoiler: você vê uma única operação FETCH que pode executar o MAX e a projeção é feita sem um segundo FETCH.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
cbq>explicar selecionar MAX([preço,teste])de teste; { "requestID":"b735ce5f-700c-4740-a065-6d4ba681129f", "assinatura":"json", "resultados":[ { "#operator":"Sequência", "~crianças":[ { "#operator":"PrimaryScan", "índice":"#primary", "espaço-chave":"teste", "namespace":"default", "usando":"gsi" }, { "#operator":"Paralelo", "~child":{ "#operator":"Sequência", "~crianças":[ { "#operator":"Buscar", "espaço-chave":"teste", "namespace":"default" }, { "#operator":"InitialGroup" (Grupo inicial), "agregados":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] } ] } }, { "#operator":"IntermediateGroup" (Grupo intermediário), "agregados":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] }, { "#operator":"FinalGroup" (Grupo Final), "agregados":[ "max([(`test`.`price`), `test`])" ], "group_keys":[] }, { "#operator":"Paralelo", "~child":{ "#operator":"Sequência", "~crianças":[ { "#operator":"InitialProject" (Projeto inicial), "result_terms":[ { "expr":"max([(`test`.`price`), `test`])" } ] }, { "#operator":"FinalProject" (Projeto Final) } ] } } ] } ], "status":"sucesso", "métricas":{ "elapsedTime" (tempo decorrido):"1.8224ms", "executionTime":"1.7614ms", "resultCount":1, "resultSize":2347 } } |
Embora esse seja um truque muito legal e um grande ganho de desempenho, apenas arranhamos a superfície do que o N1QL é capaz de fazer. Há muito mais a ser descoberto com o N1QL. Você pode começar a usar o Couchbase Server e o N1QL aqui com o Guia de introdução.
———————————————————
A propósito, se você quiser experimentar isso com o SQL Server 2016 e o Couchbase 4, aqui estão os scripts para ver isso em ação;
Script do servidor SQL
Observação: execute isso em um banco de dados chamado "teste"
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
criar tabela t1(ID do produto int primário chave, preço int, nome varchar(128)); ir inserir em t1(ID do produto,preço,nome) valores(1,10,'a'); inserir em t1(ID do produto,preço,nome) valores(2,9,'b'); inserir em t1(ID do produto,preço,nome) valores(3,12,'c'); inserir em t1(ID do produto,preço,nome) valores(4,11,'d'); inserir em t1(ID do produto,preço,nome) valores(5,1,'e'); ir definir estatísticas perfil em ir selecionar máximo(preço),ID do produto,nome de t1 ir --Msg 8120, Nível 16, Estado 1, Linha 10 --Coluna 't1.productID' é inválido em o selecionar lista porque ele é não contido em ou e agregado função ou o GRUPO BY cláusula. selecionar ID do produto, nome de t1 onde preço = (selecionar máximo(preço) de t1) ir |
Aqui está o script do servidor Couchbase
Observação: crie um bucket chamado "teste"
insert into test(key,value) values("1",{productID:1, price:10, name:'a'});
|
1 2 3 4 5 6 7 8 9 |
inserir em teste(chave,valor) valores("1",{ID do produto:1, preço:10, nome:'a'}); inserir em teste(chave,valor) valores("2",{"productID":2, "price" (preço):9, "name" (nome):"b"}); inserir em teste(chave,valor) valores("3",{"productID":3, "price" (preço):12, "name" (nome):"c"}); inserir em teste(chave,valor) valores("4",{"productID":4, "price" (preço):11, "name" (nome):"d"}); inserir em teste(chave,valor) valores("5",{"productID":5, "price" (preço):1, "name" (nome):"e"}); criar primário índice em teste; selecionar máximo(preço, ID do produto, nome) de t1; selecionar máximo([preço, teste]) de teste; explicar selecionar máximo([preço, teste]) de teste; |