Cassandra Indexing: the Good, the Bad and The Ugly

Within NoSQL, the operations of indexing, fetching and searching for information are intimated to the physical storage mechanisms. É importante lembrar que as linhas são armazenadas entre as máquinas, mas uma única linha é armazenada em uma única máquina. (com réplicas) as famílias de colunas são armazenadas em ordem ordenada, o que torna o questionamento de um conjunto de colunas eficiente (desde que você esteja abrangendo linhas).

O Mal : Particionamento

uma das coisas difíceis para se acostumar no início é que sem quaisquer consultas de índices que abrangem linhas pode (muito) ser ruim. Pensando no nosso modelo de Armazenamento, isso não é surpreendente. A estratégia que Cassandra usa para distribuir as linhas pelos anfitriões é chamada de particionamento.

particionamento é o ato de esculpir o intervalo de rowkeys atribuindo-os no “token ring”, que também atribui responsabilidade por um segmento (ou seja, partição) do intervalo rowkey para cada máquina. Provavelmente já viste isto quando inicializaste o teu grupo com um”token”. O token dá ao host uma localização ao longo do token ring, que atribui responsabilidade por uma seção do token range. Particionamento é o ato de mapear o rowkey no intervalo token.

existem dois divisores primários: Random and Order Preserving. Eles são devidamente nomeados. O RandomPartitioner coloca os rowkeys em fichas. Com o RandomPartitioner, o token é um hash da rowkey. Isto faz um bom trabalho de distribuir uniformemente os seus dados através de um conjunto de nós, mas torna incrivelmente difícil questionar uma gama do espaço rowkey. A partir de apenas um valor “start rowkey” e um valor “end rowkey”, Cassandra não pode determinar qual o intervalo do espaço token que você precisa. Ele essencialmente precisa realizar uma ” varredura de mesa “para responder à consulta, e uma” varredura de mesa ” em Cassandra é ruim, porque ele precisa ir para cada máquina (muito provavelmente todas as máquinas se você tem uma boa função de hash) para responder à consulta.

Agora, ao grande custo de até mesmo distribuição de dados, você pode empregar o OrderPreservingPartitioner (OPP). Não estou com o OPP. A ordem DO OPP preserva à medida que traduz os rowkeys em itens. Agora, dado um valor inicial rowkey e um valor final rowkey, Cassandra *pode* determinar exatamente quais as máquinas que têm os dados que você está procurando. Ele calcula o valor inicial para um token o valor final para um token, e simplesmente seleciona e retorna tudo no meio. Mas, preservando a ordem, a menos que seus rowkeys sejam distribuídos uniformemente pelo espaço, seus tokens também não serão e você terá um aglomerado desequilibrado, o que aumenta muito o custo de configuração e administração do aglomerado. (não vale a pena)

The Good : Secondary Indexes

Cassandra does provide a native indexing mechanism in Secondary Indexes. Os índices secundários funcionam a partir dos valores das colunas. Declara um índice secundário numa família de colunas. Datastax tem boa documentação sobre o uso. Sob o capô, Cassandra mantém uma “família de colunas ocultas” como o índice. (Veja a apresentação de Ed Anuff para detalhes) uma vez que Cassandra não mantém a informação do valor da coluna em qualquer nó, e os índices secundários estão no valor das colunas (em vez de rowkeys), uma consulta ainda precisa ser enviada para todos os nós. Além disso, não são recomendados índices secundários para conjuntos de alta cardinalidade. Ainda não procurei, mas presumo que seja por causa do modelo de dados usado na “família de colunas ocultas”. Se a família de colunas ocultas guarda uma linha por valor único (com rowkeys como colunas), então isso significaria digitalizar as linhas para determinar se elas estão dentro do intervalo na consulta.Da apresentação de Ed:

  • não recomendado para valores de cardinalidade elevados (isto é,datas temporais,datas de nascimento,palavras-chave, etc.)
  • Requer pelo menos uma comparação de igualdade em uma consulta, não é grande por menor que/maior que/intervalo de consultas
  • não ordenada – resultados estão no token de ordem, não de consulta de ordem de valor
  • Limitado a pesquisa sobre tipos de dados, Cassandra entende nativamente

Com tudo o que disse, índices secundários funcionar fora da caixa e tivemos um bom sucesso de utilizá-los em valores simples.

The Ugly: Do-It-Yourself (DIY) / Wide-Rows

agora, a beleza está nos olhos do observador. Uma das coisas bonitas sobre NoSQL é a simplicidade. As construções são simples: espaços de chaves, famílias de colunas, linhas e Colunas. Mantê-lo simples no entanto significa que às vezes você precisa tomar as coisas em suas próprias mãos.

este é o caso dos índices de fila larga. Utilizando o modelo de armazenamento de Cassandra, é fácil construir seus próprios índices, onde cada chave de linha se torna uma coluna no índice. Isto é às vezes difícil de obter a sua cabeça em torno de, mas vamos imaginar que temos um caso em que queremos selecionar todos os usuários em um código postal. A família principal de colunas de usuários é riscada no userid, zip code é uma coluna em cada linha de usuário. Podemos usar índices secundários, mas há alguns códigos postais. Em vez disso, poderíamos manter uma família de colunas com uma única linha chamada “idx_zipcode”. Poderíamos então escrever colunas nesta linha da forma “zipcode_userid”. Uma vez que as colunas são armazenadas em ordem ordenada, é rápido consultar para todas as colunas que começam com “18964” (e.g. poderíamos usar 18964_ e 18964_ZZZZZZ como valores iniciais e finais).

uma desvantagem óbvia desta abordagem é que as linhas são self-contained em um host. (novamente exceto para réplicas) isso significa que todas as consultas vão atingir um único nó. Ainda não encontrei uma boa resposta para isto.

além disso, e IMHO, a parte mais feia da indexação DIY wide-row é de uma perspectiva de cliente. Em nossa implementação, fizemos o nosso melhor para ser agnóstico de linguagem no lado do cliente, permitindo que as pessoas escolham a melhor ferramenta para o trabalho para interagir com os dados em Cassandra. Com essa mentalidade, os índices DIY apresentam alguns problemas. As linhas largas usam frequentemente teclas compostas (imagine se você tivesse um idx_ state_zip, que lhe permitiria consultar por estado e depois zip). Embora haja suporte “nativo” para chaves compostas, todas as Bibliotecas Clientes implementam sua própria versão delas (Hector, Astyanax e Thrift). Isso significa que o cliente que precisa consultar dados precisa ter a lógica adicionada para primeiro consultar o índice, e adicionalmente todos os clientes precisam construir a chave composta da mesma maneira.

A Melhorar As Coisas…

por esta mesma razão, decidimos lançar dois projetos de código aberto que ajudam a empurrar esta lógica para o lado do servidor. O primeiro projeto é Cassandra-gatilhos. Isto permite-lhe anexar actividades assíncronas para escrever em Cassandra. também lançámos a “Cassandra-Indexing”. Isto é quente fora das prensas e ainda está em sua infância (por exemplo, ele só suporta UT8Types no índice), mas a intenção é fornecer um mecanismo genérico do lado servidor que indexa os dados como seu escrito para Cassandra. Usando a mesma técnica do lado do servidor que usamos na indexação Cassandra, você simplesmente configura as colunas que deseja indexadas, e o código AOP faz o resto enquanto escreve para o alvo CF. Como sempre, perguntas, comentários e pensamentos são bem-vindos. (especialmente se eu estiver fora da base em algum lugar)

Deixe uma resposta

O seu endereço de email não será publicado.