Kolokace tabulek ve službě Azure Cosmos DB for PostgreSQL

PLATÍ PRO: Azure Cosmos DB for PostgreSQL (využívající rozšíření databáze Citus do PostgreSQL)

Kolokace znamená ukládání souvisejících informací na stejných uzlech. Dotazy můžou být rychlé, pokud jsou všechna potřebná data dostupná bez jakéhokoli síťového provozu. Společné přidělení souvisejících dat na různých uzlech umožňuje efektivní paralelní spouštění dotazů na jednotlivých uzlech.

Kolokace dat pro tabulky distribuované pomocí hodnot hash

Ve službě Azure Cosmos DB for PostgreSQL se řádek uloží do horizontálního oddílu, pokud hodnota hash v distribučním sloupci spadá do rozsahu hodnot hash horizontálního oddílu. Horizontální oddíly se stejným rozsahem hodnot hash se vždy umístí do stejného uzlu. Řádky se stejnými hodnotami distribučního sloupce jsou vždy na stejném uzlu napříč tabulkami. Koncept tabulek distribuovaných pomocí hash se označuje také jako horizontální dělení na základě řádků. V horizontálním dělení založeném na schématu se tabulky v rámci distribuovaného schématu vždy společně přidělují.

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

Praktický příklad kolokace

Zvažte následující tabulky, které můžou být součástí saaS pro víceklientské webové analýzy:

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)
);

Teď chceme odpovědět na dotazy, které může vydat řídicí panel pro zákazníky. Příkladem dotazu je vrácení počtu návštěv za poslední týden pro všechny stránky začínající na /blog v tenantovi šest.

Pokud se naše data nacházela na jednom serveru PostgreSQL, mohli bychom dotaz snadno vyjádřit pomocí bohaté sady relačních operací nabízených 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;

Pokud pracovní sada pro tento dotaz zapadá do paměti, je vhodným řešením tabulka s jedním serverem. Podívejme se na příležitosti škálování datového modelu pomocí služby Azure Cosmos DB for PostgreSQL.

Distribuce tabulek podle ID

Dotazy na jednoúčelový server se začnou zpomalovat, protože roste počet tenantů a data uložená pro každého tenanta. Pracovní sada přestane přilétá do paměti a procesor se stává kritickým bodem.

V tomto případě můžeme data horizontálně dělit napříč mnoha uzly pomocí služby Azure Cosmos DB for PostgreSQL. První a nejdůležitější volbou, které musíme udělat, když se rozhodneme horizontální dělení, je distribuční sloupec. Začněme naivním výběrem pro event_id tabulku událostí a page_id pro page tabulku:

-- naively use event_id and page_id as distribution columns

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

Když jsou data rozptýlená mezi různými pracovními procesy, nemůžeme provést spojení stejně jako na jednom uzlu PostgreSQL. Místo toho musíme vydat dva dotazy:

-- (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;

Potom je potřeba výsledky těchto dvou kroků zkombinovat aplikací.

Spouštění dotazů musí konzultovat data v horizontálních oddílech rozptýlených napříč uzly.

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

V tomto případě distribuce dat vytváří značné nevýhody:

  • Režie při dotazování na jednotlivé horizontální oddíly a spouštění více dotazů
  • Režijní náklady na Q1 vracející mnoho řádků klientovi
  • Otázka č. 2 bude velká.
  • Potřeba psát dotazy v několika krocích vyžaduje změny v aplikaci.

Data jsou rozptýlená, takže je možné paralelizovat dotazy. Je výhodné jenom v případě, že množství práce, kterou dotaz dělá, je podstatně větší než režie při dotazování na mnoho horizontálních oddílů.

Distribuce tabulek podle tenanta

Ve službě Azure Cosmos DB for PostgreSQL je zaručeno, že řádky se stejnou hodnotou distribučního sloupce budou na stejném uzlu. Počínaje časem můžeme vytvořit tabulky s distribučním sloupcem tenant_id .

-- 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 teď dokáže odpovědět na původní dotaz na jednoúčelový server beze změny (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;

Vzhledem k filtrování a připojení ke službě tenant_id služba Azure Cosmos DB for PostgreSQL ví, že celý dotaz může být zodpovězen pomocí sady společně přidělených horizontálních oddílů, které obsahují data pro daného tenanta. Jeden uzel PostgreSQL může odpovědět na dotaz v jednom kroku.

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

V některých případech je potřeba změnit dotazy a schémata tabulek tak, aby zahrnovaly ID tenanta v jedinečných omezeních a podmínkách spojení. Tato změna je obvykle jednoduchá.

Další kroky

  • Podívejte se, jak se data tenanta společně přidělují v kurzu s více tenanty.