Consulta SQL++ / N1QL

Melhorias no tratamento de listas IN no Couchbase Server 6.5

Introdução

A lista IN é comumente usada em consultas N1QL. O Couchbase Server 6.5 apresenta alguns aprimoramentos no tratamento da lista IN em consultas N1QL.

Manuseio de uma grande lista IN

Antes do Couchbase Server 6.5, o N1QL lidava com a avaliação da lista IN em tempo de execução de forma simples, comparando com cada elemento da lista IN até que uma correspondência fosse encontrada. Isso pode ser ineficiente se a lista IN for grande, ou seja, se houver muitos elementos na lista IN. O Couchbase Server 6.5 apresenta um aprimoramento para o manuseio de listas IN grandes em tempo de execução. Quando o número de elementos na lista IN excede um limite (atualmente 16), ele cria uma tabela de hash com todos os elementos da lista IN. Dessa forma, cada avaliação do predicado da lista IN torna-se uma sondagem da tabela de hash em vez de fazer muitas comparações com cada elemento da lista IN.

Lista "Static" IN

Para que essa otimização funcione, a lista IN deve ser "estática", ou seja, os valores de cada elemento da lista IN não podem mudar durante uma execução da consulta. Você pode ter uma lista IN em que todos os elementos sejam constantes ou parâmetros de consulta, por exemplo:

O ...... acima é apenas uma abreviação; você precisará preencher todos os valores se quiser executar a consulta.

Você pode misturar constantes e parâmetros de consulta na mesma lista IN:

Você também pode usar um único parâmetro de consulta para toda a lista IN:

e passar a lista IN real como um parâmetro de consulta.

Essa otimização da avaliação da lista IN não entrará em ação se a lista IN não for "estática", por exemplo, se qualquer elemento da lista IN fizer referência a qualquer campo do documento:

Nesse caso, o valor do primeiro elemento da lista IN muda durante a execução e, portanto, não podemos usar a otimização da tabela de hash para a avaliação dessa lista IN.

Cláusula IN com subconsulta

Como um caso especial de lista IN, você pode ter uma cláusula IN com uma subconsulta:

Quando a palavra-chave RAW é usada e há uma única expressão na lista de projeção, o resultado da subconsulta é uma matriz de valores. Quando a subconsulta não está correlacionada, ou seja, não há referência a nenhum campo na consulta pai, a nova otimização de usar uma tabela de hash para a avaliação do predicado da lista IN também pode ser aplicada aqui. No tempo de execução, depois que a subconsulta for executada e o resultado da execução da subconsulta for conhecido, se o conjunto de resultados contiver mais valores do que o limite, uma tabela de hash será criada com todos os valores no conjunto de resultados, e a avaliação subsequente do predicado da subconsulta se tornará uma sondagem da tabela de hash. Essa otimização da lista IN pode ser aplicada várias vezes no caso de subconsultas aninhadas:

desde que as duas subconsultas não estejam correlacionadas e o tamanho do resultado de cada subconsulta exceda o limite.

NÃO ESTÁ EM manuseio

A otimização do uso de uma tabela de hash para a avaliação da lista IN também é aplicável ao predicado NOT IN. O predicado NOT IN é avaliado da mesma forma que o predicado IN e o valor booleano resultante é simplesmente invertido.

Visibilidade da otimização da tabela de hash para avaliação da lista IN

A otimização para usar uma tabela de hash para avaliar uma lista IN grande é puramente uma otimização interna. Há pouco efeito visível externamente, exceto o fato de a consulta ser executada mais rapidamente. Devido ao uso de uma tabela de hash, o consumo de memória também aumenta ligeiramente durante a execução da consulta. O consumo adicional de memória depende obviamente do tamanho da tabela de hash, que, por sua vez, depende do número de elementos na lista IN.

Geração de intervalo de índice dinâmico para parâmetro de consulta como lista IN

Para um predicado de lista IN, se existir um índice apropriado, o planejador poderá gerar uma varredura de índice com vários intervalos, um para cada elemento da lista IN. Por exemplo:

A varredura do índice terá 3 períodos gerados:

O mesmo ocorre se os parâmetros de consulta forem usados como elementos individuais na lista IN:

São gerados os seguintes intervalos de índice:

No entanto, se um parâmetro de consulta for usado como a lista IN inteira:

Em seguida, é gerado um único intervalo de índice:

Observe que os limites inferior e superior do intervalo de índice são array_min($inlist) e array_max($inlist), respectivamente. Quando um parâmetro de consulta é usado para toda a lista IN, no momento da compilação, o tamanho da lista IN é desconhecido, portanto, é impossível gerar previamente intervalos de índice para cada elemento da lista IN. Usando o intervalo de índice atual gerado, a varredura de índice precisa fazer a varredura entre os valores mínimo e máximo dos elementos da matriz. Por exemplo, se o parâmetro de consulta fornecido para a execução da consulta for [1, 1000, 1000000], tudo o que estiver entre 1 e 1000000 será verificado pelo índice. Isso é muito ineficiente e envolve muito trabalho desnecessário.

No Couchbase Server 6.5, o tratamento desses casos é aprimorado pela geração dinâmica de intervalos de índice em tempo de execução. Quando a consulta está sendo executada, o valor do parâmetro de consulta agora é conhecido e, portanto, o número de elementos da lista IN também é conhecido. O mecanismo de execução agora tentará imitar os intervalos de índice gerados quando a lista IN for conhecida no momento da compilação, gerando dinamicamente um intervalo de índice separado para cada elemento da lista IN. Por exemplo, se [1, 1000, 1000000] for especificado como $inlist para a execução da consulta, o mecanismo de execução em tempo de execução gerará 3 intervalos de índice, semelhante a quando [1, 1000, 1000000] é especificado como uma constante na consulta. Isso permite que a varredura do índice seja muito mais precisa e evita a varredura de regiões desnecessárias do índice.

O plano de explicação para a consulta permanece o mesmo, ainda mostrando array_min($inlist) e array_max($inlist) como limites baixo e alto da extensão do índice. Um novo indicador "dynamic_in" é adicionado ao intervalo do índice:

A geração dinâmica de períodos de índice ocorre em tempo de execução. Para evitar possíveis problemas de desempenho, há um limite de 8192 intervalos quando os intervalos de índice são gerados dinamicamente. Se a lista IN passada (como parâmetro de consulta) tiver mais de 8192 elementos, essa otimização não será aplicada.

Tratamento de subconsultas e possível reescrita de consultas

O exemplo acima mostra a otimização da geração dinâmica de intervalos de índices quando a lista IN é um parâmetro de consulta. Essa otimização também é aplicável quando a lista IN é uma variável WITH ou um parâmetro de função. A variável WITH vem de outro novo recurso do Couchbase Server 6.5 - Common Table Expression (consulte https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/with.html); o parâmetro de função vem de outro novo recurso de visualização do desenvolvedor no Couchbase Server 6.5 - Funções definidas pelo usuário (consulte https://docs.couchbase.com/server/6.5/n1ql/n1ql-language-reference/userfun.html).

Entretanto, quando a cláusula IN usa uma subconsulta, essa otimização não é aplicável. Por exemplo: 

Neste exemplo, a cláusula IN tem uma subconsulta no lado direito. Se você tiver os seguintes índices definidos:

Em seguida, a explicação para a consulta acima mostra uma varredura de índice em ix_route_1 com os seguintes intervalos:

Isso significa que o índice varre todos os valores não NULL.

É possível reescrever manualmente a consulta acima para usar uma cláusula WITH:

Observando a explicação para essa consulta reescrita, agora a varredura de índice em ix_route_1 tem os seguintes intervalos:

Para a consulta reescrita, agora ela pode aproveitar a otimização para gerar dinamicamente intervalos de índice em tempo de execução.

Essa reescrita manual da consulta para tentar aproveitar a nova otimização da geração de extensão de índice dinâmico só é possível quando a subconsulta não está correlacionada. A reescrita manual da consulta não se limita a uma única subconsulta. Você também pode fazer uma reescrita de consulta manual semelhante para subconsultas aninhadas, desde que as subconsultas envolvidas não estejam correlacionadas. Por exemplo, dada a seguinte consulta:

Ela pode ser reescrita na consulta a seguir, de modo que possa aproveitar a otimização para gerar dinamicamente intervalos de índices:

Se você tiver o seguinte índice definido:

A explicação da consulta reescrita mostra intervalos de índice semelhantes no índice ix_airline_1:

indicando que a otimização da geração do intervalo de índice dinâmico está em jogo.

Resumo

O Couchbase Server 6.5 apresenta alguns aprimoramentos no tratamento da lista IN. Quando a lista IN é grande, uma tabela de hash é usada em tempo de execução para a avaliação da lista IN. Quando um parâmetro de consulta é especificado como a lista IN inteira, a geração dinâmica de extensão de índice em tempo de execução permite a execução de uma varredura de índice mais eficiente. Essas duas otimizações tornam o manuseio da lista IN muito mais eficiente. Nos casos em que a cláusula IN tem uma subconsulta não correlacionada, é possível reescrever manualmente a consulta usando expressões de tabela comuns, para aproveitar a otimização da geração dinâmica de intervalos de índices em tempo de execução.

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Bingjie Miao, engenheiro de software principal da Couchbase

Bingjie Miao é engenheiro de software principal da Couchbase. Bingjie tem 20 anos de experiência em bancos de dados relacionais e NoSQL. Sua principal área de especialização é a otimização e execução de consultas.

4 Comentários

  1. Desculpe-me por usar o blog como meio de comunicação... mas... o formulário de contato no seu site não funciona, e o e-mail de contato é devolvido dizendo que apenas "membros" podem enviar e-mails.
    O Couchbase ainda está vivo e funcionando?

    1. Denis Rosa, defensor dos desenvolvedores, Couchbase fevereiro 21, 2020 em 12:42 pm

      Você conseguiu falar com alguém?

  2. Oi Denis.

    Fui contatado por Bingjie.

    Obrigado por responder aqui :)

  3. Informações muito úteis, especialmente sobre tabela de hash e CTE para otimização de consultas.

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.