Modelo de aplicativos SaaS multilocatário no Azure Cosmos DB for PostgreSQL
APLICA-SE AO: Azure Cosmos DB for PostgreSQL (da plataforma da extensão de dados Citus para PostgreSQL)
ID do locatário como a chave de fragmento
A ID do locatário é a coluna na raiz da carga de trabalho ou a parte superior da hierarquia no modelo de dados. Por exemplo, neste esquema de comércio eletrônico SaaS, seria a ID da store:
Esse modelo de dados seria típico para uma empresa como a Shopify. Ele hospeda sites para várias stores online, em que cada store interage com seus próprios dados.
- Esse modelo de dados tem várias tabelas: stores, produtos, pedidos, itens de linha e países.
- A tabela de stores está na parte superior da hierarquia. Os produtos, pedidos e itens de linha estão associados às stores, portanto, na parte inferior da hierarquia.
- A tabela de países não está relacionada a stores individuais, está entre as stores.
Neste exemplo, store_id
, que está na parte superior da hierarquia, é o identificador do locatário. É a chave de fragmento certa. Escolher store_id
como a chave de fragmento permite colocar dados em todas as tabelas para uma única store em um único trabalho.
A colocação de tabelas por store tem vantagens:
- Fornece cobertura SQL, como chaves estrangeiras, junções. As transações de um único locatário estão localizadas em um único nó de trabalho em que cada locatário existe.
- Obtém o desempenho de milissegundo de dígito único. As consultas de um único locatário são encaminhadas para um único nó, em vez de serem paralelizadas, o que ajuda a otimizar os saltos de rede e ainda dimensionar a computação/memória.
- É dimensionada. À medida que o número de locatários aumenta, você pode adicionar nós e reequilibrar os locatários para os novos nós ou até mesmo isolar grandes locatários para seus próprios nós. O isolamento de locatários permite que você forneça recursos dedicados.
Modelo de dados ideal para aplicativo multilocatário
Neste exemplo, devemos distribuir as tabelas específicas da store por ID da store e tornar countries
uma tabela de referência.
Observe que as tabelas específicas do locatário têm a ID do locatário e são distribuídas. Em nosso exemplo, as stores, os produtos e os line_items são distribuídos. O restante das tabelas são tabelas de referência. Em nosso exemplo, a tabela de países é uma tabela de referência.
-- Distribute large tables by the tenant ID
SELECT create_distributed_table('stores', 'store_id');
SELECT create_distributed_table('products', 'store_id', colocate_with => 'stores');
-- etc for the rest of the tenant tables...
-- Then, make "countries" a reference table, with a synchronized copy of the
-- table maintained on every worker node
SELECT create_reference_table('countries');
As tabelas grandes devem ter a ID do locatário.
- Se você estiver migrando um aplicativo multilocatário existente para o Azure Cosmos DB for PostgreSQL, pode ser necessário desnormalizar um pouco e adicionar a coluna de ID do locatário às tabelas grandes se ela estiver ausente, e em seguida provisionar os valores ausentes da coluna.
- Para novos aplicativos no Azure Cosmos DB for PostgreSQL, verifique se a ID do locatário está presente em todas as tabelas específicas do locatário.
Inclua a ID do locatário nas restrições de chaves estrangeiras, exclusivas e primárias nas tabelas distribuídas na forma de uma chave composta. Por exemplo, se uma tabela tiver uma chave primária de id
, transforme-a na chave composta (tenant_id,id)
.
Não é necessário alterar as chaves para tabelas de referência.
Considerações de consulta para melhor desempenho
As consultas distribuídas que filtram a ID do locatário são executadas com mais eficiência no aplicativo multilocatário. Verifique se as consultas estão sempre no escopo de um único locatário.
SELECT *
FROM orders
WHERE order_id = 123
AND store_id = 42; -- ← tenant ID filter
É necessário adicionar o filtro de ID do locatário mesmo que as condições de filtro originais identifiquem claramente as linhas desejadas. O filtro de ID do locatário, embora pareça redundante, informa ao Azure Cosmos DB for PostgreSQL como encaminhar a consulta para um único nó de trabalho.
Da mesma forma, quando você estiver unindo duas tabelas distribuídas, verifique se ambas as tabelas estão no escopo de um único locatário. O escopo pode ser determinado garantindo que as condições de junção incluam a ID do locatário.
SELECT sum(l.quantity)
FROM line_items l
INNER JOIN products p
ON l.product_id = p.product_id
AND l.store_id = p.store_id -- ← tenant ID in join
WHERE p.name='Awesome Wool Pants'
AND l.store_id='8c69aa0d-3f13-4440-86ca-443566c1fc75';
-- ↑ tenant ID filter
Há bibliotecas auxiliares para várias estruturas de aplicativos populares que facilitam a inclusão de uma ID de locatário nas consultas. Estas são as instruções:
Próximas etapas
Agora terminamos de explorar a modelagem de dados para aplicativos escalonáveis. A próxima etapa é conectar e consultar o banco de dados com a linguagem de programação de sua escolha.