Dela via


Tabellsamlokalisering i Azure Cosmos DB för PostgreSQL

GÄLLER FÖR: Azure Cosmos DB for PostgreSQL (drivs av Citus-databastillägget till PostgreSQL)

Samlokalisering innebär att relaterad information lagras på samma noder. Frågor kan gå snabbt när alla nödvändiga data är tillgängliga utan nätverkstrafik. Genom att samlokalisera relaterade data på olika noder kan frågor köras effektivt parallellt på varje nod.

Datasamlokalisering för hash-distribuerade tabeller

I Azure Cosmos DB för PostgreSQL lagras en rad i en shard om hashvärdet i distributionskolumnen hamnar inom shard-hashintervallet. Shards med samma hash-intervall placeras alltid på samma nod. Rader med lika fördelningskolumnvärden finns alltid på samma nod mellan tabeller. Begreppet hash-distribuerade tabeller kallas även radbaserad horisontell partitionering. I schemabaserad horisontell partitionering samallokeras tabeller i ett distribuerat schema alltid.

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

Ett praktiskt exempel på samlokalisering

Tänk på följande tabeller som kan ingå i en saaS för webbanalys med flera klientorganisationer:

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 vill vi besvara frågor som kan utfärdas av en kundriktad instrumentpanel. En exempelfråga är "Returnera antalet besök under den senaste veckan för alla sidor som börjar med '/blog' i klientorganisationen sex."

Om våra data finns på en enda PostgreSQL-server kan vi enkelt uttrycka vår fråga med hjälp av den omfattande uppsättningen relationsåtgärder som erbjuds av 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;

Så länge arbetsuppsättningen för den här frågan passar i minnet är en tabell med en server en lämplig lösning. Nu ska vi överväga möjligheterna att skala datamodellen med Azure Cosmos DB for PostgreSQL.

Distribuera tabeller efter ID

Enserverfrågor börjar sakta ner när antalet klienter och data som lagras för varje klientorganisation växer. Arbetsuppsättningen slutar passa in i minnet och CPU blir en flaskhals.

I det här fallet kan vi fragmentera data över många noder med hjälp av Azure Cosmos DB för PostgreSQL. Det första och viktigaste valet vi behöver göra när vi bestämmer oss för att fragmentera är distributionskolumnen. Låt oss börja med ett naivt val av att använda event_id för händelsetabellen och page_id för page tabellen:

-- naively use event_id and page_id as distribution columns

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

När data sprids över olika arbetare kan vi inte utföra en koppling som vi skulle göra på en enda PostgreSQL-nod. I stället måste vi utfärda två frågor:

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

Därefter måste resultaten från de två stegen kombineras av programmet.

Om du kör frågorna måste du konsultera data i shards spridda över noder.

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

I det här fallet skapar datadistributionen betydande nackdelar:

  • Omkostnader från att köra frågor mot varje fragment och köra flera frågor.
  • Omkostnader för Q1 som returnerar många rader till klienten.
  • Q2 blir stort.
  • Behovet av att skriva frågor i flera steg kräver ändringar i programmet.

Data sprids så att frågorna kan parallelliseras. Det är bara fördelaktigt om mängden arbete som frågan utför är betydligt större än omkostnaderna för att fråga många shards.

Distribuera tabeller efter klientorganisation

I Azure Cosmos DB för PostgreSQL garanteras rader med samma distributionskolumnvärde att finnas på samma nod. Från och med nu kan vi skapa våra tabeller med tenant_id som distributionskolumn.

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

Nu kan Azure Cosmos DB for PostgreSQL svara på den ursprungliga frågan med en enskild server utan ändring (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;

På grund av filter och koppling på tenant_id vet Azure Cosmos DB for PostgreSQL att hela frågan kan besvaras med hjälp av uppsättningen samlokaliserade shards som innehåller data för just den klientorganisationen. En enskild PostgreSQL-nod kan besvara frågan i ett enda steg.

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

I vissa fall måste frågor och tabellscheman ändras för att inkludera klientorganisations-ID:t i unika begränsningar och kopplingsvillkor. Den här ändringen är vanligtvis enkel.

Nästa steg

  • Se hur klientdata samplaceeras i självstudien för flera klienter.