Öğretici: PostgreSQL için Azure Cosmos DB'de çalışan düğümlerindeki verileri parçalama

ŞUNLAR IÇIN GEÇERLIDIR: PostgreSQL için Azure Cosmos DB (PostgreSQL'e citus veritabanı uzantısıyla desteklenir)

Bu öğreticide, aşağıdakilerin nasıl yapılacağını öğrenmek için PostgreSQL için Azure Cosmos DB'yi kullanacaksınız:

  • Karma dağıtılmış parçalar oluşturma
  • Tablo parçalarının nereye yerleştirildiğine bakın
  • Çarpık dağılımı tanımlama
  • Dağıtılmış tablolarda kısıtlamalar oluşturma
  • Dağıtılmış verilerde sorgu çalıştırma

Ön koşullar

Bu öğretici, iki çalışan düğümüne sahip çalışan bir küme gerektirir. Çalışan bir kümeniz yoksa küme oluşturma öğreticisini izleyin ve bu öğreticiye geri dönün.

Karma dağıtılmış veriler

Tablo satırlarını birden çok PostgreSQL sunucusuna dağıtmak, PostgreSQL için Azure Cosmos DB'de ölçeklenebilir sorgular için önemli bir tekniktir. Birden çok düğüm birlikte geleneksel bir veritabanından daha fazla veri tutabilir ve çoğu durumda sorgu yürütmek için çalışan CPU'larını paralel olarak kullanabilir. Karma dağıtılmış tablolar kavramı satır tabanlı parçalama olarak da bilinir.

Önkoşullar bölümünde iki çalışan düğümüne sahip bir küme oluşturduk.

coordinator and two workers

Düzenleyici düğümün meta veri tabloları, çalışanları ve dağıtılmış verileri izler. pg_dist_node tablosundaki etkin çalışanları denetleyebiliriz.

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

Dekont

PostgreSQL için Azure Cosmos DB'deki düğüm adları bir sanal ağdaki iç IP adresleridir ve gördüğünüz gerçek adresler farklı olabilir.

Satırlar, parçalar ve yerleştirmeler

Çalışan düğümlerinin CPU ve depolama kaynaklarını kullanmak için tablo verilerini küme genelinde dağıtmamız gerekir. Bir tablonun dağıtılması, her satırı parça adı verilen bir mantıksal gruba atar. Şimdi bir tablo oluşturalım ve dağıtalım:

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

PostgreSQL için Azure Cosmos DB, dağıtım sütununun değerine göre her satırı bir parçaya atar. Bizim örneğimizde değerini olarak belirttikemail. Her satır tam olarak bir parçada yer alır ve her parça birden çok satır içerebilir.

users table with rows pointing to shards

Meta veri tablosunda sayarak görebildiğimiz gibi varsayılan olarak create_distributed_table() 32 parça pg_dist_shard:

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

PostgreSQL için Azure Cosmos DB, dağıtım sütunundaki pg_dist_shard değerin karması temelinde parçalara satır atamak için tabloyu kullanır. Karma ayrıntıları bu öğretici için önemli değildir. Önemli olan, hangi değerlerin hangi parça kimlikleriyle eşlendiğini görmek için sorgulayabiliriz:

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

Satırların parçalara eşlemesi tamamen mantıksaldır. Parçalar, PostgreSQL için Azure Cosmos DB'nin parça yerleştirmeyi çağırdığı depolama için belirli çalışan düğümlerine atanmalıdır.

shards assigned to workers

pg_dist_placement parça yerleşimlerine bakabiliriz. Bunu gördüğümüz diğer meta veri tablolarıyla birleştirmek, her parçanın nerede yaşadığını gösterir.

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

Veri dengesizliği

Bir küme, verileri çalışan düğümlerine eşit bir şekilde yerleştirdiğinizde ve ilgili verileri aynı çalışanlara yerleştirdiğinizde en verimli şekilde çalışır. Bu bölümde ilk bölüm olan yerleştirmenin tekdüzenliğine odaklanacağız.

Göstermek için tablomuz users için örnek veriler oluşturalım:

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

Parça boyutlarını görmek için parçalar üzerinde tablo boyutu işlevlerini çalıştırabiliriz.

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

Parçaların eşit boyutta olduğunu görebiliyoruz. Yerleşimlerin çalışanlar arasında eşit bir şekilde dağıtıldığını gördük, bu nedenle çalışan düğümlerinin kabaca eşit sayıda satır barındırdığını çıkarabiliriz.

Örneğimizdeki users satırlar, dağıtım sütununun emailözellikleri nedeniyle eşit dağıtılmıştır.

  1. E-posta adresi sayısı parça sayısından büyük veya buna eşitti.
  2. E-posta adresi başına satır sayısı benzerdi (bizim örneğimizde, e-postayı anahtar olarak bildirdiğimiz için adres başına tam olarak bir satır).

Her iki özelliğin de başarısız olduğu herhangi bir tablo ve dağıtım sütunu seçimi, çalışanlarda eşit olmayan veri boyutuyla, yani veri dengesizliğiyle sonuçlanır.

Dağıtılmış verilere kısıtlama ekleme

PostgreSQL için Azure Cosmos DB'yi kullanmak, veritabanı kısıtlamaları da dahil olmak üzere ilişkisel bir veritabanının güvenliğinden yararlanmaya devam etmenizi sağlar. Ancak bir sınırlama vardır. Dağıtılmış sistemlerin doğası gereği PostgreSQL için Azure Cosmos DB, çalışan düğümleri arasında benzersizlik kısıtlamalarına veya bilgi tutarlılığına çapraz başvuru yapmaz.

İlişkili bir tabloyla tablo örneğimizi users ele alalım.

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

Verimlilik için, sahibin e-posta adresine göre ile aynı şekilde usersdağıtırızbooks. Benzer sütun değerleriyle dağıtma işlemine birlikte bulundurma adı verilir.

Yabancı anahtara sahip kitapları kullanıcılara dağıtırken sorun yaşamadık çünkü anahtar bir dağıtım sütunundaydı. Ancak, anahtar oluşturma isbn konusunda sorun yaşamamız gerekir:

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

Dağıtılmış bir tabloda yapabileceğimiz en iyi şey sütunları dağıtım sütununu benzersiz bir şekilde modüle etmektir:

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

Yukarıdaki kısıtlama yalnızca isbn'yi kullanıcı başına benzersiz hale getirir. Bir diğer seçenek de kitapları dağıtılmış tablo yerine başvuru tablosu yapmak ve kitapları kullanıcılarla ilişkilendiren ayrı bir dağıtılmış tablo oluşturmaktır.

Dağıtılmış tabloları sorgulama

Önceki bölümlerde dağıtılmış tablo satırlarının çalışan düğümlerindeki parçalara nasıl yerleştirildiğine değindik. Çoğu zaman verilerin kümede nasıl veya nerede depolandığını bilmeniz gerekmez. PostgreSQL için Azure Cosmos DB'de normal SQL sorgularını otomatik olarak bölen dağıtılmış bir sorgu yürütücüsü vardır. Bunları verilere yakın çalışan düğümlerinde paralel olarak çalıştırır.

Örneğin, kullanıcıların yaş ortalamasını bulmak için bir sorgu çalıştırabilir ve dağıtılmış users tabloyu koordinatördeki normal bir tablo gibi ele alabiliriz.

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

query going to shards via coordinator

Arka planda PostgreSQL için Azure Cosmos DB yürütücüsü her parça için ayrı bir sorgu oluşturur, bunları çalışanlar üzerinde çalıştırır ve sonucu birleştirir. PostgreSQL EXPLAIN komutunu kullanıyorsanız bunu görebilirsiniz:

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)

Çıktı, parça 102040 üzerinde (çalışan 10.0.0.21 üzerindeki tablousers_102040) çalışan bir sorgu parçası için yürütme planı örneğini gösterir. Diğer parçalar benzer olduğundan gösterilmez. Çalışan düğümlerinin parça tablolarını taradığını ve toplamayı uyguladığını görebiliriz. Koordinatör düğümü, nihai sonuç için toplamları birleştirir.

Sonraki adımlar

Bu öğreticide dağıtılmış bir tablo oluşturduk ve parçaları ve yerleşimleri hakkında bilgi edindik. Benzersizlik ve yabancı anahtar kısıtlamalarını kullanmanın zorluğunu gördük ve son olarak dağıtılmış sorguların yüksek düzeyde nasıl çalıştığını gördük.