Projetar tabelas escalonáveis e de alto desempenho
Dica
O conteúdo deste artigo se aplica ao armazenamento de Tabelas do Azure original. No entanto, os mesmos conceitos se aplicam ao Azure Cosmos DB for Table mais recente, que oferece maior desempenho e disponibilidade, distribuição global e índices secundários automáticos. Ela também está disponível em um modo sem servidor baseado em consumo. Existem algumas diferenças de recursos entre a API de Tabela no Azure Cosmos DB e no armazenamento de Tabelas do Azure. Para obter mais informações, veja Azure Cosmos DB for Table. Para facilitar o desenvolvimento, agora fornecemos um SDK de Tabelas do Azure unificado, que pode ser usado para direcionar o armazenamento de Tabelas do Azure e o Azure Cosmos DB for Table.
Para projetar tabelas escalonáveis e de alto desempenho, você deve considerar fatores como desempenho, escalabilidade e custo. Se você tiver criado anteriormente esquemas de bancos de dados relacionais, essas considerações serão familiares, mas embora haja algumas semelhanças entre o modelo de armazenamento do serviço Tabela do Azure e os modelos relacionais, também há diferenças importantes. Normalmente, essas diferenças resultam em designs diferentes que podem parecer contraintuitivos ou errados para alguém que esteja familiarizado com bancos de dados relacionais, mas que fazem sentido se você estiver criando para um armazenamento de chave/valor de NoSQL, como o serviço Tabela do Azure. Muitas das suas diferenças de design refletem o fato de que o serviço Tabela foi projetado para dar suporte a aplicativos de escala de nuvem que podem conter bilhões de entidades (ou linhas na terminologia de banco de dados relacional) de dados ou de conjuntos de dados que devem dar suporte a grandes volumes de transações. Portanto, você deve pensar de modo diferente sobre como armazenar os dados e entender como funciona o serviço tabela. Um repositório de dados NoSQL bem projetado pode permitir que sua solução seja muito mais dimensionável e a um custo menor do que uma solução que usa um banco de dados relacional. Este guia ajuda você com esses tópicos.
Sobre o serviço Tabela do Azure
Esta seção destaca alguns dos principais recursos do serviço Tabela que são especialmente relevantes para o projeto de desempenho e escalabilidade. Se você estiver começando agora a usar o Armazenamento do Azure e o serviço Tabela, leia primeiro Introdução ao Armazenamento de Tabelas do Azure usando o .NET antes de ler o restante deste artigo. Embora o foco deste guia seja no serviço Tabela, ele inclui discussão dos serviços de Blob e fila do Azure e como você pode usá-los com o serviço Tabela.
O que é o serviço Tabela? Como você pode esperar do nome, o serviço Tabela usa um formato tabular para armazenar dados. Na terminologia padrão, cada linha da tabela representa uma entidade e as colunas armazenam várias propriedades da entidade. Cada entidade tem um par de chaves para identificar exclusivamente e uma coluna de carimbo de data/hora que o serviço Tabela usa para controlar quando a entidade foi atualizada pela última vez. O carimbo de data/hora é aplicado automaticamente e não é possível substituir manualmente o carimbo de data/hora com um valor arbitrário. O serviço Tabela usa este carimbo de data/hora (LMT) da última modificação para gerenciar a simultaneidade otimista.
Observação
As operações de API REST do serviço Tabela também retornam um valor ETag que deriva do LMT. Este documento usa os termos ETag e LMT indistintamente porque eles se referem aos mesmos dados subjacentes.
O exemplo a seguir mostra uma estrutura de tabela simples para armazenar entidades de funcionário e departamento. Muitos dos exemplos mostrados posteriormente neste guia baseiam-se neste design simples.
PartitionKey | RowKey | Timestamp | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Marketing | 00001 | 2014-08-22T00:50:32Z |
| ||||||||
Marketing | 00002 | 2014-08-22T00:50:34Z |
| ||||||||
Marketing | department | 2014-08-22T00:50:30Z |
|
||||||||
Sales | 00010 | 2014-08-22T00:50:44Z |
|
Até agora, esses dados parecem semelhantes a uma tabela no banco de dados relacional com as diferenças principais sendo as colunas obrigatórias e a capacidade de armazenar vários tipos de entidade na mesma tabela. Além disso, cada uma das propriedades definidas pelo usuário, como FirstName ou Age, tem um tipo de dados, como número inteiro ou cadeia de caracteres, semelhante a uma coluna em um banco de dados relacional. Embora diferente em um banco de dados relacional, a natureza sem esquema do serviço Tabela significa que uma propriedade não precisa ter o mesmo tipo de dados em cada entidade. Para armazenar tipos de dados complexos em uma única propriedade, você deve usar um formato serializado como JSON ou XML. Para obter mais informações sobre o serviço Tabela, como tipos de dados com suporte, intervalos de datas com suporte, regras de nomenclatura e restrições de tamanho, consulte Noções básicas sobre o modelo de dados do serviço Tabela.
Sua escolha de PartitionKey e RowKey é fundamental para um bom design da tabela. Cada entidade armazenada em uma tabela deve ter uma combinação exclusiva de PartitionKey e RowKey. Assim como acontece com as chaves em uma tabela de banco de dados relacional, os valores PartitionKey e RowKey são indexados para criar um índice clusterizado para habilitar pesquisas rápidas. No entanto, o serviço Tabela não cria qualquer índice secundário, portanto PartitionKey e RowKey são as únicas propriedades indexadas. Alguns dos padrões descritos em Padrões de design de tabela ilustram como você pode contornar essa limitação aparente.
Uma tabela contém uma ou mais partições, e muitas das decisões de design tomadas serão em torno da escolha de uma PartitionKey e uma RowKey adequadas para otimizar sua solução. Uma solução pode consistir em uma única tabela que contém todas as suas entidades organizadas em partições, mas normalmente uma solução tem várias tabelas. Tabelas o ajudarão a organizar suas entidades logicamente, gerenciar o acesso aos dados usando listas de controle de acesso, e você pode remover uma tabela inteira usando uma única operação de armazenamento.
Partições de tabela
O nome da conta, o nome de tabela e PartitionKey juntas identificam a partição dentro do serviço de armazenamento no qual o serviço Tabela armazena a entidade. Além de ser parte do esquema de endereçamento de entidades, as partições definem um escopo para transações (consulte Transações de Grupo de Entidades abaixo) e forme a base de como o serviço Tabela pode ser dimensionado. Para obter mais informações sobre partições, consulte Lista de verificação de desempenho e escalabilidade para armazenamento de tabela .
No serviço Tabela, um nó individual atende a uma ou mais partições completas e o serviço é dimensionado pelo balanceamento dinâmico de carga das partições nos nós. Se um nó estiver sob carga, o serviço Tabela pode dividir o intervalo de partições atendidas por esse nó em nós diferentes. Quando o tráfego baixa, o serviço pode mesclar os intervalos de partições de nós silenciosos de volta para um único nó.
Para obter mais informações sobre os detalhes internos do serviço Tabela e, em particular, sobre como o serviço gerencia partições, confira o artigo Armazenamento do Microsoft Azure: um serviço de armazenamento em nuvem altamente disponível com coerência forte.
Transações de Grupo de Entidades
No serviço Tabela, EGTs (Transações de Grupo de Entidades) são o único mecanismo interno para realizar atualizações atômicas entre várias entidades. EGTs são, às vezes, também conhecidas como transações de lote. EGTs só podem operar em entidades armazenadas na mesma partição (ou seja, compartilham a mesma chave de partição em uma determinada tabela). Portanto, sempre que você precisar de comportamento transacional atômico entre várias entidades, certifique-se de que as entidades estejam na mesma partição. Isso geralmente é um motivo para manter vários tipos de entidade na mesma tabela (e partição) e não usar várias tabelas para tipos de entidade diferentes. Uma única EGT pode operar no máximo 100 entidades. Se você enviar várias EGTs simultâneas para processamento, é importante garantir que essas EGTs não operem em entidades comuns entre as EGTs; caso contrário, o processamento pode ser retardado.
EGTs também apresentam uma desvantagem potencial para avaliar em seu design. Ou seja, usar mais partições aumenta a escalabilidade do seu aplicativo, porque o Azure tem mais oportunidades para solicitações de balanceamento de carga entre nós. Mas o uso de mais partições pode limitar a capacidade de seu aplicativo para executar transações atômicas e manter a consistência sólida para seus dados. Além disso, existem destinos de escalabilidade específica no nível de uma partição que pode limitar a taxa de transferência de transações que você pode esperar para um único nó. Para obter mais informações sobre destinos de escalabilidade para contas de armazenamento padrão do Azure, consulte Destinos de escalabilidade para contas de armazenamento padrão. Para obter mais informações sobre as metas de escalabilidade do serviço Tabela, confira Metas de escalabilidade e desempenho do Armazenamento de Tabelas.
Considerações sobre a capacidade
A tabela a seguir descreve a capacidade, escalabilidade e metas de desempenho para o Armazenamento de Tabelas.
Recurso | Destino |
---|---|
Número de tabelas em uma conta de armazenamento do Azure | Limitado apenas pela capacidade da conta de armazenamento |
Número de partições em uma tabela | Limitado apenas pela capacidade da conta de armazenamento |
Número de entidades em uma partição | Limitado apenas pela capacidade da conta de armazenamento |
Tamanho máximo de uma única tabela | 500 TiB |
Tamanho máximo de uma única entidade, incluindo todos os valores de propriedade | 1 MiB |
Número máximo de propriedades em uma entidade de tabela | 255 (incluindo as três propriedades do sistema, PartitionKey, RowKey e Timestamp) |
Tamanho total máximo de uma propriedade individual em uma entidade | Varia por tipo de propriedade. Para obter mais informações, confira a seção Tipos de propriedade em Noções básicas sobre o modelo de dados do serviço tabela. |
Tamanho do PartitionKey | Uma cadeia de caracteres com até 1024 caracteres de tamanho |
Tamanho do RowKey | Uma cadeia de caracteres com até 1024 caracteres de tamanho |
Tamanho de uma transação de grupo de entidades | Uma transação pode incluir no máximo 100 entidades e o conteúdo deve ser menor que 4 MiB. Uma transação de grupo de entidades pode incluir uma atualização para uma entidade apenas uma vez. |
Número máximo de políticas de acesso armazenadas por tabela | 5 |
Taxa máxima de solicitação por conta de armazenamento | 20 mil transações por segundo, o que supõe um tamanho de entidade de 1 KiB |
Taxa de transferência de destino para uma partição de tabela única (entidades de 1 KiB) | Até 2 mil entidades por segundo |
Considerações de custo
Armazenamento de tabela é relativamente barato, mas você deve incluir estimativas de custo para a utilização da capacidade e a quantidade de transações como parte de sua avaliação de qualquer solução do serviço Tabela. No entanto, em muitos cenários, o armazenamento de dados duplicados ou desnormalizados para melhorar o desempenho ou a escalabilidade de sua solução é uma abordagem válida. Para obter mais informações sobre preços, consulte Preços de Armazenamento do Azure.