Práticas recomendadas de design de esquemas
Esta página contém informações sobre a conceção do esquema do Bigtable. Antes de ler esta página, deve conhecer a vista geral do Bigtable. Esta página aborda os seguintes tópicos:
- Conceitos gerais: conceitos básicos a ter em conta ao conceber o seu esquema.
- Práticas recomendadas: diretrizes de design que se aplicam à maioria dos casos de utilização, discriminadas por componente da tabela.
- Exemplos de utilização especiais: recomendações para alguns exemplos de utilização e padrões de dados específicos.
Conceitos gerais
A conceção de um esquema do Bigtable é diferente da conceção de um esquema para uma base de dados relacional. Um esquema do Bigtable é definido pela lógica da aplicação, em vez de um objeto ou um ficheiro de definição de esquema. Pode adicionar famílias de colunas a uma tabela quando cria ou atualiza a tabela, mas as colunas e os padrões de chaves de linhas são definidos pelos dados que escreve na tabela.
No Bigtable, um esquema é um projeto ou um modelo de uma tabela, incluindo a estrutura dos seguintes componentes da tabela:
- Chaves de linhas
- Famílias de colunas, incluindo as respetivas políticas de recolha de lixo
- Colunas
No Bigtable, a conceção do esquema é determinada principalmente pelas consultas, ou pedidos de leitura, que planeia enviar para a tabela. Uma vez que ler um intervalo de linhas é a forma mais rápida de ler os seus dados do Bigtable, as recomendações nesta página foram concebidas para ajudar a otimizar as leituras de intervalos de linhas. Na maioria dos casos, isto significa enviar uma consulta com base em prefixos de chaves de linhas.
Uma consideração secundária é a evitação de pontos críticos. Para evitar pontos críticos, tem de considerar padrões de escrita e como pode evitar aceder a um pequeno espaço de chaves num curto período de tempo.
Os seguintes conceitos gerais aplicam-se à conceção do esquema do Bigtable:
- O Bigtable é um armazenamento de chave/valor e não um armazenamento relacional. Não suporta junções e as transações só são suportadas numa única linha.
- Cada tabela tem um índice: a chave da linha. Cada chave de linha tem de ser única. Para criar um índice secundário, use uma vista materializada contínua. Para mais informações, consulte o artigo Crie um índice secundário assíncrono.
- As chaves de linha ordenam as linhas lexicograficamente da string de bytes mais baixa para a mais alta. Esta ordem é big-endian (por vezes, denominada ordem de bytes de rede), o equivalente binário da ordem alfabética.
- As famílias de colunas não são armazenadas por nenhuma ordem específica.
- As colunas são agrupadas por família de colunas e ordenadas por ordem lexicográfica
na família de colunas. Por exemplo, numa família de colunas denominada
SysMonitorcom qualificadores de colunas deProcessName,User,%CPU,ID,Memory,DiskReadePriority, o Bigtable armazena as colunas nesta ordem:
| SysMonitor | ||||||
|---|---|---|---|---|---|---|
| %CPU | DiskRead | ID | Memória | Prioridade | ProcessName | Utilizador |
- A interseção de uma linha e uma coluna pode conter várias células com indicação de data/hora. Cada célula contém uma versão única com data/hora dos dados dessa linha e coluna.
- As famílias de colunas agregadas contêm células agregadas. Pode criar famílias de colunas que contenham apenas células agregadas. Uma agregação permite-lhe unir novos dados com dados já existentes na célula.
- Todas as operações são atómicas ao nível da linha. Uma operação afeta uma linha inteira ou nenhuma parte da linha.
- Idealmente, as leituras e as escritas devem ser distribuídas uniformemente pelo espaço de linhas de uma tabela.
- As tabelas do Bigtable são esparsas. Uma coluna não ocupa espaço numa linha que não usa a coluna.
Práticas recomendadas
Um bom esquema resulta num excelente desempenho e escalabilidade, e um esquema mal concebido pode levar a um sistema com um desempenho fraco. Cada exemplo de utilização é diferente e requer o seu próprio design, mas as seguintes práticas recomendadas aplicam-se à maioria dos exemplos de utilização. As exceções são indicadas.
Começando ao nível da tabela e avançando para o nível da chave da linha, as secções seguintes descrevem as práticas recomendadas para o design do esquema:
Todos os elementos da tabela, especialmente as chaves das linhas, devem ser concebidos tendo em conta os pedidos de leitura planeados. Verifique as quotas e os limites recomendados e os limites de tamanho rígidos para todos os elementos da tabela.
Uma vez que todas as tabelas numa instância são armazenadas nos mesmos tablets, um esquema que resulte em hotspots numa tabela pode afetar a latência de outras tabelas na mesma instância. Os pontos ativos são causados pelo acesso frequente a uma parte da tabela num curto período de tempo.
Tabelas
Armazene conjuntos de dados com esquemas semelhantes na mesma tabela, em vez de em tabelas separadas.
Noutros sistemas de base de dados, pode optar por armazenar dados em várias tabelas com base no assunto e no número de colunas. No entanto, no Bigtable, é geralmente melhor armazenar todos os dados numa única tabela. Pode atribuir um prefixo de chave de linha exclusivo para usar em cada conjunto de dados, para que o Bigtable armazene os dados relacionados num intervalo contíguo de linhas que pode consultar por prefixo de chave de linha.
O Bigtable tem um limite de 1000 tabelas por instância, mas recomendamos que evite criar um grande número de tabelas pelos seguintes motivos:
- O envio de pedidos para muitas tabelas diferentes pode aumentar a sobrecarga da ligação de back-end, o que resulta num aumento da latência final.
- A criação de mais tabelas não melhora o equilíbrio de carga e pode aumentar os custos gerais de gestão.
Pode querer justificadamente uma tabela separada para um exemplo de utilização diferente que exija um esquema diferente, mas não deve usar tabelas separadas para dados semelhantes. Por exemplo, não deve criar uma nova tabela porque é um novo ano ou tem um novo cliente.
Famílias de colunas
Coloque colunas relacionadas na mesma família de colunas. Quando uma linha contém vários valores relacionados entre si, é uma boa prática agrupar as colunas que contêm esses valores na mesma família de colunas. Agrupe os dados o mais próximo possível para evitar ter de criar filtros complexos e para obter apenas as informações de que precisa, mas não mais, nos seus pedidos de leitura mais frequentes.
Crie até cerca de 100 famílias de colunas por tabela. A criação de mais de 100 famílias de colunas pode causar uma degradação do desempenho.
Escolha nomes curtos para as suas famílias de colunas. Os nomes estão incluídos nos dados transferidos para cada pedido.
Coloque colunas com diferentes necessidades de retenção de dados em diferentes famílias de colunas. Esta prática é importante se quiser limitar os custos de armazenamento. As políticas de recolha de lixo são definidas ao nível da família de colunas e não ao nível da coluna. Por exemplo, se só precisar de manter a versão mais recente de um determinado dado, não o armazene numa família de colunas definida para armazenar 1000 versões de outra coisa. Caso contrário, está a pagar para armazenar 999 células de dados de que não precisa.
Colunas
Crie tantas colunas quantas precisar na tabela. As tabelas do Bigtable são esparsas e não existe penalização de espaço para uma coluna que não seja usada numa linha. Pode ter milhões de colunas numa tabela, desde que nenhuma linha exceda o limite máximo de 256 MB por linha.
Evite usar demasiadas colunas numa única linha. Embora uma tabela possa ter milhões de colunas, uma linha não deve ter. Existem alguns fatores que contribuem para esta prática recomendada:
- O Bigtable demora algum tempo a processar cada célula numa linha.
- Cada célula adiciona alguma sobrecarga à quantidade de dados armazenados na tabela e enviados através da rede. Por exemplo, se estiver a armazenar 1 KB (1024 bytes) de dados, é muito mais eficiente em termos de espaço armazenar esses dados numa única célula, em vez de distribuir os dados por 1024 células que contêm 1 byte cada.
Se o seu conjunto de dados exigir logicamente mais colunas por linha do que o Bigtable consegue processar de forma eficiente, considere armazenar os dados como um protobuf numa única coluna.
Opcionalmente, pode tratar os qualificadores de colunas como dados. Uma vez que tem de armazenar um qualificador de coluna para cada coluna, pode poupar espaço ao dar um nome à coluna com um valor. Por exemplo, considere uma tabela que armazena dados sobre amizades numa Friendsfamília de colunas. Cada linha representa uma pessoa e todas as suas
amizades. Cada qualificador de coluna pode ser o ID de um amigo. Em seguida, o valor de cada coluna nessa linha pode ser o círculo social em que o amigo está. Neste exemplo, as linhas podem ter o seguinte aspeto:
| Chave da linha | Frederico | Gabriel | Hiroshi | Seo Yoon | Jakob |
|---|---|---|---|---|---|
| Jose | book-club | trabalho | ténis | ||
| Sófia | trabalho | escola | chess-club |
Contraste este esquema com um esquema para os mesmos dados que não trata os qualificadores de colunas como dados e, em vez disso, tem as mesmas colunas em todas as linhas:
| Chave da linha | Amigo | Círculo |
|---|---|---|
| Jose#1 | Frederico | book-club |
| Jose#2 | Gabriel | trabalho |
| Jose#3 | Hiroshi | ténis |
| Sofia#1 | Hiroshi | trabalho |
| Sofia#2 | Seo Yoon | escola |
| Sofia#3 | Jakob | chess-club |
O segundo design do esquema faz com que a tabela cresça muito mais rapidamente.
Se estiver a usar qualificadores de colunas para armazenar dados, atribua aos qualificadores de colunas nomes curtos, mas significativos. Esta abordagem permite-lhe reduzir a quantidade de dados transferidos para cada pedido. O tamanho máximo é de 16 KB.
Linhas
Mantenha o tamanho de todos os valores numa única linha abaixo de 100 MB. Certifique-se de que os dados numa única linha não excedem 256 MB. As linhas que excedem este limite podem resultar numa redução do desempenho de leitura.
Mantenha todas as informações de uma entidade numa única linha. Para a maioria dos exemplos de utilização, evite armazenar dados que tem de ler de forma atómica ou tudo de uma vez em mais do que uma linha para evitar inconsistências. Por exemplo, se atualizar duas linhas numa tabela, é possível que uma linha seja atualizada com êxito e a outra atualização falhe. Certifique-se de que o seu esquema não requer a atualização de mais do que uma linha em simultâneo para que os dados relacionados sejam precisos. Esta prática garante que, se parte de um pedido de gravação falhar ou tiver de ser enviado novamente, esse conjunto de dados não fica temporariamente incompleto.
Exceção: se manter uma entidade numa única linha resultar em linhas com centenas de MB, deve dividir os dados em várias linhas.
Armazene entidades relacionadas em linhas adjacentes para tornar as leituras mais eficientes.
Células
Não armazene mais de 10 MB de dados numa única célula. Lembre-se de que uma célula é o dado armazenado para uma determinada linha e coluna com uma data/hora única e que podem ser armazenadas várias células na interseção dessa linha e coluna. O número de células retidas numa coluna é regido pela política de recolha de lixo que define para a família de colunas que contém essa coluna.
Use células agregadas para armazenar e atualizar dados agregados. Se só se preocupar com o valor agregado dos eventos de uma entidade, como a soma mensal das vendas por funcionário numa loja de retalho, pode usar agregações. Para mais informações, consulte o artigo Agregue valores no momento da gravação.
Chaves de linhas
Crie a chave da linha com base nas consultas que vai usar para obter os dados. As chaves de linhas bem concebidas permitem o melhor desempenho do Bigtable. As consultas do Bigtable mais eficientes obtêm dados através de um dos seguintes métodos:
- Chave da linha
- Prefixo da chave da linha
- Intervalo de linhas definido pelas chaves de linhas inicial e final
Outros tipos de consultas acionam uma análise completa da tabela, que é muito menos eficiente. Se escolher a chave da linha correta agora, pode evitar um processo de migração de dados difícil mais tarde.
Mantenha as chaves de linhas curtas. Uma chave de linha tem de ter 4 KB ou menos. As chaves de linhas longas ocupam memória e armazenamento adicionais, e aumentam o tempo necessário para receber respostas do servidor do Bigtable.
Armazenar vários valores delimitados em cada chave de linha. Uma vez que a melhor forma de consultar o Bigtable de forma eficiente é através da chave da linha, é frequentemente útil incluir vários identificadores na chave da linha. Quando a chave da linha inclui vários valores, é especialmente importante ter uma compreensão clara de como usa os seus dados.
Os segmentos de chave de linha são normalmente separados por um delimitador, como dois pontos, uma barra, ou um símbolo de hash. O primeiro segmento ou conjunto de segmentos contíguos é o prefixo da chave da linha e o último segmento ou conjunto de segmentos contíguos é o sufixo da chave da linha.
Os prefixos de chaves de linhas bem planeados permitem tirar partido da ordem de ordenação incorporada do Bigtable para armazenar dados relacionados em linhas contíguas. Armazenar dados relacionados em linhas contíguas permite-lhe aceder a dados relacionados como um intervalo de linhas, em vez de executar análises de tabelas ineficientes.
Se os seus dados incluírem números inteiros que quer armazenar ou ordenar numericamente, preencha os números inteiros com zeros à esquerda. O Bigtable armazena dados lexicograficamente. Por exemplo, lexicograficamente, 3 > 20, mas 20 > 03. O preenchimento do 3 com um zero inicial garante que os números são ordenados numericamente. Esta tática é importante para as indicações de tempo em que são usadas consultas baseadas em intervalos.
É importante criar uma chave de linha que permita obter um intervalo de linhas bem definido. Caso contrário, a sua consulta requer uma análise da tabela, que é muito mais lenta do que a obtenção de linhas específicas.
Por exemplo, se a sua aplicação monitorizar dados de dispositivos móveis, pode ter uma chave de linha que consista no tipo de dispositivo, no ID do dispositivo e no dia em que os dados são registados. As chaves de linhas para estes dados podem ter o seguinte aspeto:
phone#4c410523#20200501
phone#4c410523#20200502
tablet#a0b81f74#20200501
tablet#a0b81f74#20200502
Este design de chave de linha permite-lhe obter dados com um único pedido para:
- Um tipo de dispositivo
- Uma combinação do tipo de dispositivo e do ID do dispositivo
Este design de chave de linha