Zelfstudie: Shard-gegevens op werkknooppunten in Azure Cosmos DB for PostgreSQL

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

In deze zelfstudie gebruikt u Azure Cosmos DB for PostgreSQL voor meer informatie over het volgende:

  • Shards met hashverdeling maken
  • Zien waar tabelshards worden geplaatst
  • Ongelijke distributie identificeren
  • Beperkingen voor gedistribueerde tabellen maken
  • Query's uitvoeren op gedistribueerde gegevens

Vereisten

Voor deze zelfstudie is een actief cluster met twee werkknooppunten vereist. Als u geen actief cluster hebt, volgt u de zelfstudie cluster maken en gaat u terug naar dit cluster.

Gegevens met hashverdeling

Het distribueren van tabelrijen over meerdere PostgreSQL-servers is een belangrijke techniek voor schaalbare query's in Azure Cosmos DB voor PostgreSQL. Meerdere knooppunten kunnen samen meer gegevens bevatten dan een traditionele database, en kunnen in veel gevallen werkrol-CPU's parallel gebruiken om query's uit te voeren. Het concept van hash-gedistribueerde tabellen wordt ook wel sharding op basis van rijen genoemd.

In de sectie Vereisten hebben we een cluster met twee werkknooppunten gemaakt.

coordinator and two workers

Met de tabellen met metagegevens van het coördinatorknooppunt kunnen werkrollen en gedistribueerde gegevens worden bijgehouden. We kunnen de actieve werkrollen controleren in de tabel pg_dist_node.

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

Notitie

Knooppuntnamen in Azure Cosmos DB for PostgreSQL zijn interne IP-adressen in een virtueel netwerk en de werkelijke adressen die u ziet, kunnen verschillen.

Rijen, shards en plaatsingen

Als u de CPU- en opslagbronnen van werkknooppunten wilt gebruiken, moeten we tabelgegevens over het hele cluster verdelen. Als u een tabel distribueert, wordt elke rij toegewezen aan een logische groep die een shard wordt genoemd. Laten we een tabel maken en deze distribueren:

-- 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 wijst elke rij toe aan een shard op basis van de waarde van de distributiekolom, die we in ons geval hebben emailopgegeven. Elke rij komt precies in één shard, en elke shard kan meerdere rijen bevatten.

users table with rows pointing to shards

create_distributed_table() maakt standaard 32 shards, zoals we kunnen zien als we de metagegevenstabel pg_dist_shard meetellen:

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

Azure Cosmos DB for PostgreSQL gebruikt de pg_dist_shard tabel om rijen toe te wijzen aan shards, op basis van een hash van de waarde in de distributiekolom. De hashdetails zijn niet belangrijk voor deze zelfstudie. Wat belangrijk is, is dat we een query kunnen uitvoeren om te zien welke waarden zijn toegewezen aan welke shard-id's:

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

Het toewijzen van rijen aan shards gebeurt alleen op basis van logica. Shards moeten worden toegewezen aan specifieke werkknooppunten voor opslag, in wat Azure Cosmos DB for PostgreSQL shardplaatsing aanroept.

shards assigned to workers

We kunnen de shardplaatsing in pg_dist_placement bekijken. Door deze te koppelen aan de andere tabellen met metagegevens die we hebben gezien, wordt duidelijk waar elke shard zich bevindt.

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

Ongelijkheid in gegevens

Een cluster wordt het meest efficiënt uitgevoerd wanneer u gegevens gelijkmatig op werkknooppunten plaatst en wanneer u gerelateerde gegevens op dezelfde werkrollen plaatst. In deze sectie richten we ons op het eerste gedeelte, de uniformiteit van plaatsing.

Ter demonstratie maken we voorbeeldgegevens voor de tabel users:

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

Als we shardgrootten willen zien, kunnen we functies voor tabelgrootte uitvoeren voor de shards.

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

We zien dat de shards even groot zijn. We hebben al gezien dat plaatsingen gelijkmatig zijn gedistribueerd over werkrollen. We kunnen dus afleiden dat de werkknooppunten ongeveer hetzelfde aantal rijen bevatten.

De rijen in ons voorbeeld users zijn gelijkmatig gedistribueerd vanwege eigenschappen van de distributiekolom email.

  1. Het aantal e-mailadressen is groter dan of gelijk aan het aantal shards.
  2. Het aantal rijen per e-mailadres is vergelijkbaar (in ons geval is er precies één rij per adres, omdat we het e-mailadres in een sleutel hebben gedeclareerd).

Een willekeurige tabel en distributiekolom waarbij een van de eigenschappen mislukt, bevat uiteindelijk ongelijke gegevensgrootten in werkrollen, dit wordt ongelijkheid in gegevens genoemd.

Beperkingen toevoegen aan gedistribueerde gegevens

Met Azure Cosmos DB for PostgreSQL kunt u blijven profiteren van de veiligheid van een relationele database, inclusief databasebeperkingen. Er is echter een limiet. Vanwege de aard van gedistribueerde systemen, worden in Azure Cosmos DB for PostgreSQL geen beperkingen voor uniekheid of referentiële integriteit tussen werkknooppunten kruisverwijzingen gebruikt.

Laten we onze voorbeeldtabel users erbij nemen met een gerelateerde tabel.

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

Voor efficiëntiedoeleinden hebben we books op dezelfde manier gedistribueerd als users: via het e-mailadres van de eigenaar. Distributie op basis van vergelijkbare kolomwaarden heet colocatie.

We hebben boeken zonder problemen met een refererende sleutel gedistribueerd naar gebruikers, omdat de sleutel zich bij een distributiekolom bevond. We zouden echter problemen ondervinden om van isbn een sleutel te maken:

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

In een gedistribueerde tabel is van de unieke modulo van kolommen de distributiekolom maken het beste wat we kunnen doen:

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

Met de bovenstaande beperking wordt alleen de ISBN uniek gemaakt per gebruiker. Een andere optie is om van boeken een referentietabel te maken, in plaats van een gedistribueerde tabel, en een afzonderlijke gedistribueerde tabel te maken die boeken koppelt aan gebruikers.

Query uitvoeren op gedistribueerde tabellen

In de vorige secties hebben we gezien hoe gedistribueerde tabelrijen in shards worden geplaatst op werkknooppunten. Meestal hoeft u niet te weten hoe of waar gegevens worden opgeslagen in een cluster. Azure Cosmos DB for PostgreSQL heeft een gedistribueerde queryexecutor waarmee normale SQL-query's automatisch worden gesplitst. De query's worden parallel uitgevoerd op werkknooppunten dicht bij de gegevens.

We kunnen bijvoorbeeld een query uitvoeren om de gemiddelde leeftijd van gebruikers te vinden, waarbij we de gedistribueerde tabel users behandelen alsof het een normale tabel is in de coördinator.

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

query going to shards via coordinator

Achter de schermen maakt de Azure Cosmos DB for PostgreSQL-uitvoerder een afzonderlijke query voor elke shard, voert deze uit op de werkrollen en combineert het resultaat. U kunt deze zien met behulp van de PostgreSQL-opdracht 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)

De uitvoer toont een voorbeeld van een uitvoeringsplan voor een queryfragment dat wordt uitgevoerd voor shard 102040 (de tabel users_102040 op werkrol 10.0.0.21). De andere fragmenten worden niet weergegeven omdat ze vergelijkbaar zijn. We zien dat op het werkknooppunt de shardtabellen worden gescand en de samenvoeging toegepast. Op het coördinatorknooppunt worden samenvoegingen gecombineerd voor het uiteindelijke resultaat.

Volgende stappen

In deze zelfstudie hebt u een gedistribueerde tabel gemaakt, en informatie gekregen over de bijbehorende shards en plaatsingen. U hebt gezien dat het gebruik van beperkingen voor uniekheid en refererende sleutels een uitdaging vormen, en ten slotte hoe gedistribueerde query's werken op hoog niveau.