Dela via


Självstudie: Shard-data på arbetsnoder i Azure Cosmos DB för PostgreSQL

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

I den här självstudien använder du Azure Cosmos DB for PostgreSQL för att lära dig hur du:

  • Skapa hash-distribuerade shards
  • Se var tabellshards placeras
  • Identifiera skev fördelning
  • Skapa begränsningar för distribuerade tabeller
  • Köra frågor på distribuerade data

Förutsättningar

Den här självstudien kräver ett kluster som körs med två arbetsnoder. Om du inte har ett kluster som körs följer du självstudien skapa kluster och går sedan tillbaka till den här.

Hash-distribuerade data

Att distribuera tabellrader över flera PostgreSQL-servrar är en viktig teknik för skalbara frågor i Azure Cosmos DB för PostgreSQL. Tillsammans kan flera noder lagra mer data än en traditionell databas och kan i många fall använda arbets-PROCESSORer parallellt för att köra frågor. Begreppet hash-distribuerade tabeller kallas även radbaserad horisontell partitionering.

I avsnittet förutsättningar skapade vi ett kluster med två arbetsnoder.

koordinator och två arbetare

Koordinatornodens metadatatabeller spårar arbetare och distribuerade data. Vi kan kontrollera aktiva arbetare i tabellen pg_dist_node .

select nodeid, nodename from pg_dist_node where isactive;
 nodeid | nodename
--------+-----------
      1 | 10.0.0.21
      2 | 10.0.0.23

Kommentar

Nodenames i Azure Cosmos DB for PostgreSQL är interna IP-adresser i ett virtuellt nätverk, och de faktiska adresser som du ser kan skilja sig åt.

Rader, fragment och placeringar

För att kunna använda processor- och lagringsresurserna för arbetsnoder måste vi distribuera tabelldata i hela klustret. När du distribuerar en tabell tilldelas varje rad till en logisk grupp som kallas shard . Nu ska vi skapa en tabell och distribuera den:

-- create a table on the coordinator
create table users ( email text primary key, bday date not null );

-- distribute it into shards on workers
select create_distributed_table('users', 'email');

Azure Cosmos DB for PostgreSQL tilldelar varje rad till en shard baserat på värdet för distributionskolumnen, som vi i vårt fall angav som email. Varje rad kommer att finnas i exakt en shard och varje shard kan innehålla flera rader.

användartabell med rader som pekar på shards

Som standard create_distributed_table() görs 32 shards, som vi kan se genom att räkna i metadatatabellen pg_dist_shard:

select logicalrelid, count(shardid)
  from pg_dist_shard
 group by logicalrelid;
 logicalrelid | count
--------------+-------
 users        |    32

Azure Cosmos DB for PostgreSQL använder pg_dist_shard tabellen för att tilldela rader till shards, baserat på en hash av värdet i distributionskolumnen. Hashinformationen är oviktig för den här självstudien. Det viktiga är att vi kan fråga för att se vilka värden som mappar till vilka shard-ID:ar:

-- Where would a row containing hi@test.com be stored?
-- (The value doesn't have to actually be present in users, the mapping
-- is a mathematical operation consulting pg_dist_shard.)
select get_shard_id_for_distribution_column('users', 'hi@test.com');
 get_shard_id_for_distribution_column
--------------------------------------
                               102008

Mappningen av rader till shards är helt logisk. Shards måste tilldelas till specifika arbetsnoder för lagring, i vad Azure Cosmos DB for PostgreSQL anropar horisontell placering.

shards tilldelade till arbetare

Vi kan titta på shardplaceringarna i pg_dist_placement. När vi går med i de andra metadatatabellerna som vi har sett visas var varje fragment finns.

-- limit the output to the first five placements

select
	shard.logicalrelid as table,
	placement.shardid as shard,
	node.nodename as host
from
	pg_dist_placement placement,
	pg_dist_node node,
	pg_dist_shard shard
where placement.groupid = node.groupid
  and shard.shardid = placement.shardid
order by shard
limit 5;
 table | shard  |    host
-------+--------+------------
 users | 102008 | 10.0.0.21
 users | 102009 | 10.0.0.23
 users | 102010 | 10.0.0.21
 users | 102011 | 10.0.0.23
 users | 102012 | 10.0.0.21

Skjuvade data

Ett kluster körs mest effektivt när du placerar data jämnt på arbetsnoder och när du placerar relaterade data tillsammans på samma arbetare. I det här avsnittet fokuserar vi på den första delen, placeringens enhetlighet.

För att demonstrera ska vi skapa exempeldata för vår users tabell:

-- load sample data
insert into users
select
	md5(random()::text) || '@test.com',
	date_trunc('day', now() - random()*'100 years'::interval)
from generate_series(1, 1000);

Om du vill se fragmentstorlekar kan vi köra tabellstorleksfunktioner på fragmenten.

-- sizes of the first five shards
select *
from
	run_command_on_shards('users', $cmd$
	  select pg_size_pretty(pg_table_size('%1$s'));
	$cmd$)
order by shardid
limit 5;
 shardid | success | result
---------+---------+--------
  102008 | t       | 16 kB
  102009 | t       | 16 kB
  102010 | t       | 16 kB
  102011 | t       | 16 kB
  102012 | t       | 16 kB

Vi kan se att fragmenten är lika stora. Vi har redan sett att placeringarna är jämnt fördelade mellan arbetare, så vi kan dra slutsatsen att arbetsnoderna har ungefär lika många rader.

Raderna i vårt users exempel distribueras jämnt eftersom egenskaperna för distributionskolumnen, email.

  1. Antalet e-postadresser var större än eller lika med antalet shards.
  2. Antalet rader per e-postadress var liknande (i vårt fall exakt en rad per adress eftersom vi deklarerade e-post som en nyckel).

Val av tabell- och distributionskolumn där någon av egenskaperna misslyckas får ojämn datastorlek för arbetare, dvs. datasnedställning.

Lägga till begränsningar i distribuerade data

Med Hjälp av Azure Cosmos DB för PostgreSQL kan du fortsätta att njuta av säkerheten för en relationsdatabas, inklusive databasbegränsningar. Det finns dock en begränsning. På grund av de distribuerade systemens natur korsreferenser inte unika begränsningar eller referensintegritet mellan arbetsnoder i Azure Cosmos DB for PostgreSQL.

Nu ska vi överväga vårt users tabellexempel med en relaterad tabell.

-- books that users own
create table books (
	owner_email text references users (email),
	isbn text not null,
	title text not null
);

-- distribute it
select create_distributed_table('books', 'owner_email');

För effektivitets skull distribuerar books vi på samma sätt som users: via ägarens e-postadress. Distribution med liknande kolumnvärden kallas colocation.

Vi hade inga problem med att distribuera böcker med en sekundärnyckel till användare, eftersom nyckeln fanns i en distributionskolumn. Vi skulle dock ha problem med att göra isbn en nyckel:

-- will not work
alter table books add constraint books_isbn unique (isbn);
ERROR:  cannot create constraint on "books"
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or
        PRIMARY KEY constraints that do not include the partition column
        (with an equality operator if EXCLUDE).

I en distribuerad tabell är det bästa vi kan göra kolumner unika modulo distributionskolumnen:

-- a weaker constraint is allowed
alter table books add constraint books_isbn unique (owner_email, isbn);

Ovanstående villkor gör bara isbn unikt per användare. Ett annat alternativ är att göra böcker till en referenstabell i stället för en distribuerad tabell och skapa en separat distribuerad tabell som associerar böcker med användare.

Fråga distribuerade tabeller

I föregående avsnitt såg vi hur distribuerade tabellrader placeras i shards på arbetsnoder. För det mesta behöver du inte veta hur eller var data lagras i ett kluster. Azure Cosmos DB for PostgreSQL har en distribuerad frågeexekutor som automatiskt delar upp vanliga SQL-frågor. De körs parallellt på arbetsnoder nära data.

Vi kan till exempel köra en fråga för att hitta användarnas genomsnittliga ålder och behandla den distribuerade users tabellen som om den vore en normal tabell i koordinatorn.

select avg(current_date - bday) as avg_days_old from users;
    avg_days_old
--------------------
 17926.348000000000

fråga som går till shards via koordinator

I bakgrunden skapar Azure Cosmos DB for PostgreSQL-kören en separat fråga för varje shard, kör dem på arbetarna och kombinerar resultatet. Du kan se om du använder kommandot PostgreSQL EXPLAIN:

explain select avg(current_date - bday) from users;
                                  QUERY PLAN
----------------------------------------------------------------------------------
 Aggregate  (cost=500.00..500.02 rows=1 width=32)
   ->  Custom Scan (Citus Adaptive)  (cost=0.00..0.00 rows=100000 width=16)
     Task Count: 32
     Tasks Shown: One of 32
     ->  Task
       Node: host=10.0.0.21 port=5432 dbname=citus
       ->  Aggregate  (cost=41.75..41.76 rows=1 width=16)
         ->  Seq Scan on users_102040 users  (cost=0.00..22.70 rows=1270 width=4)

Utdata visar ett exempel på en körningsplan för ett frågefragment som körs på shard 102040 (tabellen users_102040 på worker 10.0.0.21). De andra fragmenten visas inte eftersom de liknar varandra. Vi kan se att arbetsnoden söker igenom shardtabellerna och tillämpar aggregeringen. Koordinatornoden kombinerar aggregeringar för slutresultatet.

Nästa steg

I den här självstudien skapade vi en distribuerad tabell och lärde oss om dess shards och placeringar. Vi såg en utmaning med att använda unika och sekundärnyckelbegränsningar och såg slutligen hur distribuerade frågor fungerar på en hög nivå.