Escolher colunas de distribuição no Azure Cosmos DB for PostgreSQL

APLICA-SE A: Azure Cosmos DB for PostgreSQL (da plataforma da extensão de dados Citus para PostgreSQL)

Escolher a coluna de distribuição de cada tabela é uma das decisões de modelagem mais importantes que você tomará. O Azure Cosmos DB for PostgreSQL armazena linhas em fragmentos com base no valor da coluna de distribuição das linhas.

A opção correta agrupa os dados relacionados nos mesmos nós físicos, o que torna as consultas rápidas e adiciona suporte a todos os recursos do SQL. Uma opção incorreta faz com que o sistema seja executado lentamente.

Dicas gerais

Veja a seguir quatro critérios para escolher a coluna de distribuição ideal para suas tabelas distribuídas.

  1. Escolha uma coluna que seja central na carga de trabalho do aplicativo.

    Você pode considerar essa coluna como o "coração", a "parte central" ou a "dimensão natural" do particionamento de dados.

    Exemplos:

    • device_id em uma carga de trabalho de IoT
    • security_id para um aplicativo financeiro que acompanha valores mobiliários
    • user_id na análise de usuários
    • tenant_id para um aplicativo SaaS multilocatário
  2. Escolha uma coluna com cardinalidade razoável e uma distribuição estatística uniforme.

    A coluna deve ter muitos valores e distribui-los de maneira completa e uniforme entre todos os fragmentos.

    Exemplos:

    • Cardinalidade acima de 1000
    • Não escolha uma coluna que tenha o mesmo valor em um grande percentual de linhas (distorção de dados)
    • Em uma carga de trabalho de SaaS, ter um locatário muito maior do que o restante pode causar distorção de dados. Para essa situação, você pode usar o isolamento de locatário para criar um fragmento dedicado para tratar o locatário.
  3. Escolha uma coluna que beneficie as consultas existentes.

    Para uma carga de trabalho transacional ou operacional (em que a maioria das consultas leva apenas alguns milissegundos), escolha uma coluna que seja exibida como um filtro em cláusulas WHERE em, pelo menos, 80% das consultas. Por exemplo, a coluna device_id em SELECT * FROM events WHERE device_id=1.

    Para uma carga de trabalho analítica (na qual a maioria das consultas leva de 1 a 2 segundos), escolha uma coluna que permita que as consultas sejam paralelizadas entre nós de trabalho. Por exemplo, uma coluna que ocorre com frequência em cláusulas GROUP BY ou que é consultada em vários valores ao mesmo tempo.

  4. Escolha uma coluna que esteja presente na maioria das tabelas grandes.

    As tabelas acima de 50 GB devem ser distribuídas. A escolha da mesma coluna de distribuição para todas elas permite que você coloque os dados dessa coluna em nós de trabalho. A colocação torna eficiente a execução de junções e rollups e a imposição de chaves estrangeiras.

    As outras tabelas (menores) podem ser tabelas locais ou de referência. Se a tabela menor precisar ser unida às tabelas distribuídas, torne-a uma tabela de referência.

Exemplos de casos de uso

Vimos critérios gerais para a escolha da coluna de distribuição. Agora, vamos ver como eles se aplicam a casos de uso comuns.

Aplicativos multilocatário

A arquitetura de multilocatário usa uma forma de modelagem de banco de dados hierárquica para distribuir consultas entre os nós do cluster. O início da hierarquia de dados é conhecida como a ID do locatário e precisa ser armazenada em uma coluna de cada tabela.

O Azure Cosmos DB for PostgreSQL inspeciona consultas para ver qual ID de locatário elas envolvem e localiza o fragmento de tabela correspondente. Ela roteia a consulta para um nó de trabalho individual que contém o fragmento. A execução de uma consulta com todos os dados relevantes colocados no mesmo nó é chamada de colocação.

O diagrama a seguir ilustra a colocação no modelo de dados multilocatário. Ele contém duas tabelas, Contas e Campanhas, cada uma distribuída pela account_id. As caixas sombreadas representam fragmentos. Os fragmentos verdes são armazenados juntos em um nó de trabalho, e os fragmentos azuis são armazenados em outro nó de trabalho. Observe como uma consulta de junção entre Contas e Campaigns tem todos os dados necessários juntos em um nó quando as duas tabelas são restritas à mesma account_id.

Multilocação de locatário

Para aplicar esse design a um esquema próprio, identifique o que constitui um locatário no seu aplicativo. As instâncias comuns incluem empresa, conta, organização ou cliente. O nome da coluna será semelhante a company_id ou customer_id. Examine cada uma das consultas e faça esta pergunta: isso funcionará se ela tiver mais cláusulas WHERE para restringir todas as tabelas envolvidas às linhas com a mesma ID de locatário? As consultas no modelo de multilocatário estão no escopo de um locatário. Por exemplo, as consultas sobre as vendas ou o inventário estão no escopo de uma loja específica.

Práticas recomendadas

  • Distribua as tabelas por uma coluna tenant_id comum. Por exemplo, em um aplicativo SaaS em que os locatários são empresas, provavelmente, a tenant_id será a company_id.
  • Converta pequenas tabelas entre locatários em tabelas de referência. Quando vários locatários compartilharem uma pequena tabela de informações, distribua-a como uma tabela de referência.
  • Restrinja e filtre todas as consultas de aplicativo por tenant_id. Cada consulta deve solicitar informações para um locatário por vez.

Leia o tutorial sobre multilocatário para obter um exemplo de como criar esse tipo de aplicativo.

Aplicativos em tempo real

A arquitetura de multilocatário apresenta uma estrutura hierárquica e usa a colocação de dados para rotear consultas por locatário. Por outro lado, as arquiteturas em tempo real dependem de propriedades de distribuição específicas dos dados para obter um processamento altamente paralelo.

Usamos a "ID da entidade" como um termo para colunas de distribuição no modelo em tempo real. As entidades típicas são usuários, hosts ou dispositivos.

As consultas em tempo real normalmente solicitam agregações numéricas agrupadas por data ou categoria. O Azure Cosmos DB for PostgreSQL envia essas consultas a cada fragmento para resultados parciais e junta a resposta final no nó coordenador. As consultas são executadas mais rapidamente quando muitos nós contribuem o máximo possível e quando nenhum nó precisa realizar uma quantidade desproporcional de trabalho.

Práticas recomendadas

  • Escolha uma coluna com alta cardinalidade como a coluna de distribuição. Para comparação, um campo Status em uma tabela de pedidos com os valores Novo, Pago e Enviado é uma opção inadequada de coluna de distribuição. Ele pressupõe apenas esses poucos valores, o que limita o número de fragmentos que podem conter os dados e o número de nós que podem processá-lo. Entre as colunas com alta cardinalidade, também é bom escolher as colunas que são usadas com frequência em cláusulas group-by ou como chaves de junção.
  • Escolha uma coluna com distribuição uniforme. Se você distribuir uma tabela em uma coluna distorcida para determinados valores comuns, os dados da tabela tenderão a ser acumulados em alguns fragmentos. Os nós que mantêm esses fragmentos acabam realizando mais trabalho do que os outros nós.
  • Distribua tabelas de fatos e dimensões nas colunas comuns. A tabela de fatos só pode ter uma chave de distribuição. As tabelas unidas em outra chave não serão colocalizadas com a tabela de fatos. Escolha uma dimensão a ser colocalizada com base na frequência na qual ela é unida e no tamanho das linhas de junção.
  • Altere algumas tabelas de dimensões para tabelas de referência. Se uma tabela de dimensões não puder ser colocalizada com a tabela de fatos, aprimore o desempenho da consulta distribuindo cópias da tabela de dimensões para todos os nós na forma de uma tabela de referência.

Leia o tutorial sobre o painel em tempo real para obter um exemplo de como criar esse tipo de aplicativo.

Dados de série temporal

Em uma carga de trabalho de série temporal, os aplicativos consultam informações recentes enquanto arquivam informações antigas.

O erro mais comum ao modelar informações de série temporal no Azure Cosmos DB for PostgreSQL é usar o próprio carimbo de data/hora como uma coluna de distribuição. Uma distribuição de hash com base no tempo distribui os tempos de modo aleatória em fragmentos diferentes, em vez de manter os intervalos de tempo juntos em fragmentos. As consultas que envolvem tempo geralmente referenciam intervalos de tempo, por exemplo, os dados mais recentes. Esse tipo de distribuição de hash leva à sobrecarga da rede.

Práticas recomendadas

  • Não escolha um carimbo de data/hora como a coluna de distribuição. Escolha outra coluna de distribuição. Em um aplicativo multilocatário, use a ID do locatário, ou em um aplicativo em tempo real, use a ID da entidade.
  • Em vez disso, use o particionamento de tabela do PostgreSQL para a hora. Use o particionamento de tabela para dividir uma tabela grande de dados ordenados por hora em várias tabelas herdadas com cada tabela que contém intervalos de tempo diferentes. A distribuição de uma tabela particionada do Postgres cria fragmentos para as tabelas herdadas.

Próximas etapas