Esta página explica como projetar o esquema para uma tabela do Cloud Bigtable. Antes de continuar, leia a página Visão geral do Cloud Bigtable.
Conceitos gerais
Projetar um esquema do Cloud Bigtable é muito diferente de projetar um esquema para um banco de dados relacional. Ao projetar um do Cloud Bigtable, lembre-se dos seguintes pontos:
- Cada tabela tem apenas um índice: a chave de linha. Não há índices secundários.
- As linhas são classificadas lexicograficamente por chave de linha, da string com menos bytes para a com mais. As chaves de linha são classificadas por bytes big-endian ou de rede, o equivalente binário à ordem alfabética.
- Todas as operações são atômicas no nível da linha. Por exemplo, se você atualizar duas linhas em uma tabela, possivelmente uma linha será atualizada com êxito, e a outra falhará. Evite projetar esquemas que necessitam de atomicidade entre linhas.
- O ideal é que leituras e gravações sejam distribuídas uniformemente por todo o espaço das linhas da tabela.
- Em geral, mantenha todas as informações de uma entidade em uma única linha. Uma entidade que não necessita de atualizações e leituras atômicas pode ser divididas em várias linhas. Recomenda-se dividir entidades com grande volume de dados (centenas de MB) em várias linhas.
- As entidades relacionadas devem ser armazenadas em linhas adjacentes, tornando as leituras mais eficientes.
- As tabelas do Cloud Bigtable são esparsas. As colunas vazias não ocupam espaço. Como resultado, geralmente, o mais sensato é criar um grande número de colunas, mesmo se a maioria estiver vazia em muitas linhas.
Limites de tamanho
Como prática recomendada, verifique se o esquema respeita os limites de tamanho abaixo:
- chaves de linha: 4 KB por chave
- grupos de colunas: aproximadamente 100 grupos por tabela
- qualificadores de coluna: 16 KB por qualificador
- valores individuais: aproximadamente 10 MB por célula
- todos os valores em uma única linha: aproximadamente 100 MB
Além disso, é necessário que o esquema permita que você fique abaixo destes limites rígidos:
- valores individuais: 100 MB por célula
- todos os valores em uma única linha: 256 MB
- tabelas: 1.000 por cluster
As leituras das linhas são realizadas atomicamente. Portanto, é muito importante limitar a quantidade total de dados armazenados em uma única linha. Por exemplo, se você tentar realizar a leitura de 25 linhas com cada uma contendo 100 MB de dados e a sua instância tiver somente 2 GB de RAM disponível, um erro por falta de memória será acionado.
Como escolher uma chave de linha
Para o melhor desempenho possível do Cloud Bigtable, é essencial pensar cuidadosamente em como compor a chave de linha. Isso é importante porque as consultas mais eficientes do Cloud Bigtable usam a chave de linha, um prefixo ou um intervalo de linhas para recuperar os dados. Outros tipos de consultas acionam a verificação total da tabela, o que é bem menos eficiente. Se você escolher agora a chave de linha correta, evitará um complicado processo de migração de dados mais tarde.
Comece questionando como serão usados os dados que você planeja armazenar. Por exemplo:
- informações de usuários: você precisa de acesso rápido a informações sobre conexões entre usuários (por exemplo, se o usuário A segue o usuário B)?
- conteúdo gerado pelo usuário: se você mostra aos demais usuários uma amostra de uma grande quantidade de conteúdo gerado por um usuário, como atualizações de status, como decidir o que será exibido?
- dados de série temporal: você precisará recuperar com frequência os registros N mais recentes ou de um determinado período de tempo? Se você estiver armazenando dados de vários tipos de eventos, será necessário filtrá-los com base no tipo de evento?
Se você entender suas necessidades desde o início, sua chave de linha e o seu esquema terão como oferecer a flexibilidade suficiente para a realização de consultas eficientes aos dados.
Tipos de chaves de linha
Esta seção descreve alguns dos tipos de chaves de linha mais comuns, além de explicar quando usar cada um.
Como regra básica, mantenha as chaves de linha curtas, na medida do possível. Chaves de linha compridas ocupam um espaço adicional de memória e armazenamento, além de aumentarem o tempo necessário para receber as respostas do servidor do Cloud Bigtable.
Nomes de domínio inversos
Se você estiver armazenando dados sobre entidades que podem ser representadas como nomes de domínio, pense em usar como chave de linha o nome de domínio inverso (por exemplo, com.company.product). Usá-lo assim é uma ótima ideia, principalmente se os dados de uma linha normalmente se sobrepuserem às colunas adjacentes. Nesse caso, o Cloud Bigtable será mais eficiente ao compactar os dados.
Essa abordagem funciona melhor quando os dados estão espalhados por muitos nomes de domínio inversos diferentes. Se você pretende armazenar a maior parte dos dados em um número pequeno de nomes de domínio inversos, pense em atribuir outros valores à chave de linha. Caso contrário, você poderá sobrecarregar um bloco, empurrando a maioria das gravações para um único node no cluster.
Identificadores de string
Se você estiver armazenando dados sobre entidades que podem ser identificadas por uma string simples (por exemplo, códigos de usuário), use o identificador da string como chave de linha ou parte dela. Pense em usar, em vez do próprio identificador, um hash pertencente a ele. Assim, o identificador sempre terá um comprimento previsível. Usar um hash é ainda mais útil quando vários valores são combinados em uma única chave de linha, como discutido abaixo.
Timestamps
Se você frequentemente precisa recuperar dados com base na data e hora em que foram gravados, uma boa solução é incluir um timestamp como parte da chave de linha. Não é recomendável usar somente o timestamp como chave de linha, pois a maioria das gravações seria empurrada para um único node. Pelo mesmo motivo, evite colocar o timestamp no início da chave de linha.
Por exemplo, digamos que o seu aplicativo precise gravar, a cada segundo, dados relacionados a desempenho de um grande número de máquinas, como utilização de CPU e memória.
A chave de linha desses dados poderia ser uma combinação de identificador da máquina e timestamp dos dados (por exemplo, machine_4223421#1425330757685).
Se você normalmente recupera primeiro os registros mais recentes, é possível usar um timestamp invertido na chave de linha, subtraindo o timestamp do valor máximo da linguagem de programação para números inteiros longos (em Java, java.lang.Long.MAX_VALUE). Com o timestamp invertido, os registros serão ordenados do mais recente para o mais antigo.
Vários valores em uma única chave de linha
Como a única maneira de realizar consultas no Cloud Bigtable com eficiência é utilizando a chave de linha, na maioria dos casos, é muito útil incluir vários identificadores nela. Quando a chave de linha contém vários valores, é muito importante ter um entendimento claro de como os dados serão usados.
Por exemplo, digamos que o seu aplicativo permita aos usuários postar mensagens e mencionar uns aos outros nas postagens. Você deseja encontrar uma forma eficiente de listar todos os usuários que marcaram um usuário específico em uma postagem. Uma maneira de fazer isso é usar uma chave de linha que contenha o hash do nome de usuário marcado seguido do hash do nome de usuário que fez a tagging. Cada linha armazenaria os nomes de usuário sem hash junto com os dados da postagem:
Para descobrir quem marcou um nome de usuário específico ou mostrar todas as postagens com a tag desse nome de usuário, basta recuperar o intervalo de linhas cujas chaves comecem pelo nome de usuário.
Conforme demonstrado no exemplo, é importante criar uma chave de linha que ainda permita recuperar um intervalo de linhas bem definido. Caso contrário, sua consulta necessitará de uma verificação da tabela, o que é muito mais lento do que recuperar linhas específicas. Por exemplo, imagine que você armazena dados relacionados a desempenho a cada segundo. Se a chave de linha consistir em um timestamp seguido pelo identificador da máquina (por exemplo, 1425330757685#machine_4223421), não haverá uma maneira eficiente de limitar a consulta a apenas uma máquina específica. A consulta somente poderá ser limitada com base no timestamp.
Chaves de linha a ser evitadas
Alguns tipos de chave de linha podem dificultar a consulta aos dados ou resultar em um desempenho insatisfatório. Esta seção descreve os tipos de chave de linha que você deve evitar no Cloud Bigtable.
Nomes de domínio
Evite usar nomes de domínio não inversos ou padrão como chaves de linha. O uso de nomes de domínio padrão torna ineficiente a recuperação de todas as linhas dentro de uma parte do domínio. Por exemplo, todas as linhas relacionadas a company.com estarão em intervalos de linhas separados, como services.company.com, product.company.com e assim por diante. Além disso, usar nomes de domínio padrão faz com que as linhas sejam classificadas de tal forma que os dados relacionados não são agrupados em um único lugar. Isso resulta em uma compactação menos eficiente.
Códigos numéricos sequenciais
Suponha que o seu sistema atribua um código numérico para cada usuário do seu aplicativo. Provavelmente, você ficará tentado a usar o código numérico do usuário como chave de linha na sua tabela. No entanto, como é mais provável que os usuários novos sejam mais ativos, essa abordagem poderá empurrar a maior parte do tráfego para um número pequeno de nodes.
Uma abordagem segura é usar uma versão invertida do código numérico do usuário, distribuindo, assim, o tráfego de maneira uniforme para todos os nodes da tabela do Cloud Bigtable.
Identificadores estáticos atualizados repetidamente
Evite usar uma única chave de linha para identificar um valor que é atualizado com muita frequência. Por exemplo, se você armazenar dados de utilização de memória a cada segundo, não use uma única chave de linha com o nome memusage nem atualize a linha repetidamente.
Esse tipo de operação sobrecarrega o bloco que armazena a linha usada com muita frequência.
Isso também pode fazer com que a linha exceda o limite de tamanho, já que os valores anteriores de cada célula continuam ocupando espaço por um período de tempo.
Em vez disso, armazene um valor por linha, usando a chave de linha que contém o tipo de métrica, um delimitador e um timestamp. Por exemplo, para rastrear a utilização da memória ao longo do tempo, use chaves de linha semelhantes a memusage#1423523569918. Essa é uma estratégia eficiente porque criar uma linha nova no Cloud Bigtable não demora mais do que criar uma célula nova. Além disso, é possível realizar rapidamente a leitura dos dados a partir de um período específico, calculando as chaves inicial e final adequadas.
Com relação aos valores alterados com muita frequência, como um contador que é atualizado centenas de vezes por minuto, o melhor é simplesmente manter os dados na memória, na camada do aplicativo, e periodicamente gravar linhas novas no Cloud Bigtable.
Grupos de colunas e qualificadores de coluna
Esta seção fornece orientações sobre como considerar grupos de colunas e qualificadores de coluna na tabela.
Grupos de colunas
Diferentemente do HBase, no Cloud Bigtable, é possível usar até cerca de 100 grupos de colunas sem prejudicar o desempenho. Como resultado, sempre que uma linha contiver vários valores inter-relacionados, recomenda-se agrupar esses valores no mesmo grupo de colunas. Reunir dados em grupos de colunas permite recuperar os dados de um ou vários grupos, em vez de recuperar todos os dados de cada linha. Agrupe os dados o mais próximo possível para receber apenas as informações necessárias nas chamadas de API mais frequentes.
Além disso, os nomes dos grupos de colunas devem ser curtos, pois eles estão inclusos nos dados transferidos em cada solicitação.
Qualificadores de coluna
Como as tabelas do Cloud Bigtable são esparsas, é possível criar quantos qualificadores de coluna você achar necessário em cada linha. Não há penalidade de espaço para células vazias em uma linha. Portanto, muitas vezes faz sentido tratar os qualificadores de coluna como dados. Por exemplo, se a sua tabela armazena postagens de usuários, use o identificador exclusivo de cada postagem como qualificador de coluna.
Assim como no caso das chaves de linha e dos grupos de colunas, é bom manter os nomes dos qualificadores de coluna curtos, pois isso ajuda a minimizar a quantidade de dados transferidos em cada solicitação.
Tabelas altas x tabelas amplas
Os exemplos que você viu até agora são de tabelas amplas, nas quais uma única linha contém um número muito grande de colunas. Normalmente, são resultado do uso de qualificadores de coluna como dados. Também há casos em que faz mais sentido usar uma tabela alta, que tem um número muito grande de linhas com pouquíssimas colunas em cada uma delas.
Vamos ver novamente o exemplo do Presida, da página da visão geral:
Esse é um exemplo de uma tabela ampla que rastreia quem cada usuário segue. Para cada usuário, a tabela contém uma coluna por usuário seguido.
Suponha que você não precise da lista completa de usuários seguidos. Que você deseje usar o Cloud Bigtable apenas para responder uma pergunta mais restrita: o usuário A segue o usuário B?
Uma solução eficiente para esse caso é usar uma tabela alta, com uma linha por relação de seguidor/seguido. A chave de linha da tabela alta combina os hashes dos nomes de usuário do seguidor e do seguido. Assim, para verificar se o usuário A segue o B, basta pesquisar uma única chave de linha. Se a linha estiver presente, significa que o usuário A segue o B. Se não estiver, significa que não.
Vejamos a versão em tabela alta dos dados do Presida:
Se você quiser saber se o usuário jadams segue tjefferson, basta pesquisar a chave de linha que combina as hashes de jadams (df887e44) e de tjefferson (b0452e5c). No caso acima, veja que existe a linha df887e44b0452e5c. Portanto, sabemos que jadams segue tjefferson.
Repare que a tabela alta armazena o nome de usuário de cada pessoa seguida. Sem essa informação, levaria muito tempo para encontrar o nome de usuário que corresponde ao hash.
Mais informações
Se você estiver armazenando dados rastreados ao longo do tempo, consulte Projeto de esquema para dados de séries temporais.