Colocatie van tabellen in Azure Cosmos DB for PostgreSQL

VAN TOEPASSING OP: Azure Cosmos DB for PostgreSQL (mogelijk gemaakt door de Citus-database-extensie naar PostgreSQL)

Colocatie betekent het opslaan van gerelateerde informatie op dezelfde knooppunten. Query's kunnen snel gaan wanneer alle benodigde gegevens beschikbaar zijn zonder netwerkverkeer. Door gerelateerde gegevens op verschillende knooppunten samen te plaatsen, kunnen query's efficiënt parallel op elk knooppunt worden uitgevoerd.

Gegevenscolocatie voor hash-gedistribueerde tabellen

In Azure Cosmos DB for PostgreSQL wordt een rij opgeslagen in een shard als de hash van de waarde in de distributiekolom binnen het hashbereik van de shard valt. Shards met hetzelfde hashbereik worden altijd op hetzelfde knooppunt geplaatst. Rijen met gelijke waarden voor distributiekolommen bevinden zich altijd op hetzelfde knooppunt in tabellen. Het concept van hash-gedistribueerde tabellen wordt ook wel sharding op basis van rijen genoemd. In sharding op basis van schema's worden tabellen binnen een gedistribueerd schema altijd op een punt weergegeven.

Diagram shows shards with the same hash range placed on the same node for events shards and page shards.

Een praktisch voorbeeld van colocatie

Bekijk de volgende tabellen die deel kunnen uitmaken van een SaaS voor multitenant-webanalyse:

CREATE TABLE event (
  tenant_id int,
  event_id bigint,
  page_id int,
  payload jsonb,
  primary key (tenant_id, event_id)
);

CREATE TABLE page (
  tenant_id int,
  page_id int,
  path text,
  primary key (tenant_id, page_id)
);

Nu willen we query's beantwoorden die kunnen worden uitgegeven door een klantgericht dashboard. Een voorbeeldquery is 'Retourneert het aantal bezoeken in de afgelopen week voor alle pagina's die beginnen met '/blog' in tenant zes.'

Als onze gegevens zich op één PostgreSQL-server bevinden, kunnen we onze query eenvoudig uitdrukken met behulp van de uitgebreide set relationele bewerkingen die worden aangeboden door SQL:

SELECT page_id, count(event_id)
FROM
  page
LEFT JOIN  (
  SELECT * FROM event
  WHERE (payload->>'time')::timestamptz >= now() - interval '1 week'
) recent
USING (tenant_id, page_id)
WHERE tenant_id = 6 AND path LIKE '/blog%'
GROUP BY page_id;

Zolang de werkset voor deze query in het geheugen past, is een tabel met één server een geschikte oplossing. Laten we eens kijken naar de mogelijkheden van het schalen van het gegevensmodel met Azure Cosmos DB for PostgreSQL.

Tabellen distribueren op id

Query's met één server worden vertraagd naarmate het aantal tenants en de gegevens die voor elke tenant zijn opgeslagen, toenemen. De werkset stopt in het geheugen en cpu wordt een knelpunt.

In dit geval kunnen we de gegevens op veel knooppunten sharden met behulp van Azure Cosmos DB for PostgreSQL. De eerste en belangrijkste keuze die we moeten maken wanneer we besluiten om te sharden, is de distributiekolom. Laten we beginnen met een naïeve keuze voor het gebruik event_id van de gebeurtenistabel en page_id voor de page tabel:

-- naively use event_id and page_id as distribution columns

SELECT create_distributed_table('event', 'event_id');
SELECT create_distributed_table('page', 'page_id');

Wanneer gegevens over verschillende werkrollen worden verspreid, kunnen we geen join uitvoeren zoals op één PostgreSQL-knooppunt. In plaats daarvan moeten we twee query's uitgeven:

-- (Q1) get the relevant page_ids
SELECT page_id FROM page WHERE path LIKE '/blog%' AND tenant_id = 6;

-- (Q2) get the counts
SELECT page_id, count(*) AS count
FROM event
WHERE page_id IN (/*…page IDs from first query…*/)
  AND tenant_id = 6
  AND (payload->>'time')::date >= now() - interval '1 week'
GROUP BY page_id ORDER BY count DESC LIMIT 10;

Daarna moeten de resultaten van de twee stappen worden gecombineerd door de toepassing.

Het uitvoeren van de query's moet gegevens raadplegen in shards verspreid over knooppunten.

Diagram shows an inefficient approach that uses multiple queries against the event and page tables in two nodes.

In dit geval creëert de gegevensdistributie aanzienlijke nadelen:

  • Overhead van het uitvoeren van query's op elke shard en het uitvoeren van meerdere query's.
  • Overhead van Q1 retourneert veel rijen naar de client.
  • Q2 wordt groot.
  • Voor het schrijven van query's in meerdere stappen zijn wijzigingen in de toepassing vereist.

De gegevens worden verspreid, zodat de query's kunnen worden geparallelliseerd. Het is alleen nuttig als de hoeveelheid werk die de query uitvoert aanzienlijk groter is dan de overhead van het uitvoeren van query's op veel shards.

Tabellen per tenant distribueren

In Azure Cosmos DB for PostgreSQL zijn rijen met dezelfde distributiekolomwaarde gegarandeerd op hetzelfde knooppunt. Vanaf nu kunnen we onze tabellen maken met tenant_id als distributiekolom.

-- co-locate tables by using a common distribution column
SELECT create_distributed_table('event', 'tenant_id');
SELECT create_distributed_table('page', 'tenant_id', colocate_with => 'event');

Azure Cosmos DB for PostgreSQL kan nu de oorspronkelijke query met één server beantwoorden zonder te wijzigen (Q1):

SELECT page_id, count(event_id)
FROM
  page
LEFT JOIN  (
  SELECT * FROM event
  WHERE (payload->>'time')::timestamptz >= now() - interval '1 week'
) recent
USING (tenant_id, page_id)
WHERE tenant_id = 6 AND path LIKE '/blog%'
GROUP BY page_id;

Vanwege filter en join op tenant_id weet Azure Cosmos DB for PostgreSQL dat de hele query kan worden beantwoord met behulp van de set met gekommatuurde shards die de gegevens voor die specifieke tenant bevatten. Eén PostgreSQL-knooppunt kan de query in één stap beantwoorden.

Diagram shows a single query to one node, which is a more efficient approach.

In sommige gevallen moeten query's en tabelschema's worden gewijzigd om de tenant-id op te nemen in unieke beperkingen en joinvoorwaarden. Deze wijziging is meestal eenvoudig.

Volgende stappen

  • Bekijk hoe tenantgegevens zich in de zelfstudie met meerdere tenants bevinden.