Bagikan melalui


Tutorial: Data shard pada simpul pekerja di Azure Cosmos DB for PostgreSQL

BERLAKU UNTUK: Azure Cosmos DB for PostgreSQL (didukung oleh ekstensi database Citus ke PostgreSQL)

Dalam tutorial ini, Anda menggunakan Azure Cosmos DB for PostgreSQL untuk mempelajari cara:

  • Membuat pecahan yang didistribusikan hash
  • Melihat tempat pecahan tabel ditempatkan
  • Mengidentifikasi distribusi miring
  • Membuat batasan pada tabel terdistribusi
  • Menjalankan kueri pada data terdistribusi

Prasyarat

Tutorial ini memerlukan kluster yang sedang berjalan dengan dua simpul pekerja. Jika Anda tidak memiliki kluster yang sedang berjalan, ikuti tutorial buat kluster lalu kembali ke yang satu ini.

Data yang didistribusikan hash

Mendistribusikan baris tabel di beberapa server PostgreSQL adalah teknik utama untuk kueri yang dapat diskalakan di Azure Cosmos DB for PostgreSQL. Bersama-sama, beberapa simpul dapat menyimpan lebih banyak data daripada database tradisional, dan dalam banyak kasus dapat menggunakan CPU pekerja secara paralel untuk menjalankan kueri. Konsep tabel terdistribusi hash juga dikenal sebagai sharding berbasis baris.

Di bagian prasyarat, kami membuat kluster dengan dua simpul pekerja.

koordinator dan dua pekerja

Tabel metadata simpul koordinator melacak pekerja dan mendistribusikan data. Kami dapat memeriksa pekerja aktif di 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

Catatan

Nodename di Azure Cosmos DB for PostgreSQL adalah alamat IP internal dalam jaringan virtual, dan alamat aktual yang Anda lihat mungkin berbeda.

Baris, pecahan, dan penempatan

Untuk menggunakan sumber daya CPU dan penyimpanan simpul pekerja, kita harus mendistribusikan data tabel di seluruh kluster. Mendistribusikan tabel menetapkan setiap baris ke grup logis yang disebut shard. Mari kita membuat tabel dan mendistribusikannya:

-- 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 menetapkan setiap baris ke shard berdasarkan nilai kolom distribusi, yang, dalam kasus kami, kami menentukan menjadi email. Setiap baris akan berada di tepat satu pecahan, dan setiap pecahan dapat berisi beberapa baris.

tabel pengguna dengan baris yang menunjuk ke pecahan

Secara default create_distributed_table() membuat 32 pecahan, seperti yang dapat kami lihat dengan menghitung dalam tabel metadata pg_dist_shard:

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

Azure Cosmos DB for PostgreSQL menggunakan pg_dist_shard tabel untuk menetapkan baris ke pecahan, berdasarkan hash nilai di kolom distribusi. Detail hashing tidak penting untuk tutorial ini. Yang penting adalah bahwa kami dapat meminta untuk melihat peta nilai mana ke ID pecahan mana:

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

Pemetaan baris ke pecahan sangat logis. Shard harus ditetapkan ke simpul pekerja tertentu untuk penyimpanan, dalam penempatan shard panggilan Azure Cosmos DB for PostgreSQL.

pecahan yang ditetapkan ke pekerja

Kami dapat melihat penempatan pecahan di pg_dist_placement. Bergabung dengan tabel metadata lain yang pernah kami lihat menunjukkan tempat setiap pecahan berada.

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

Penyimpangan data

Kluster berjalan paling efisien ketika Anda menempatkan data secara merata pada simpul pekerja, dan ketika Anda menempatkan data terkait bersama-sama pada pekerja yang sama. Di bagian ini kami akan berfokus pada bagian pertama, keseragaman penempatan.

Untuk menunjukkan, mari membuat sampel data untuk 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);

Untuk melihat ukuran pecahan, kami dapat menjalankan fungsi ukuran tabel pada pecahan.

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

Kami dapat melihat pecahan berukuran sama. Kami sudah melihat bahwa penempatan didistribusikan secara merata di antara pekerja, sehingga dapat menyimpulkan bahwa simpul pekerja menyimpan jumlah baris yang hampir sama.

Baris dalam contoh users didistribusikan secara merata karena properti kolom distribusi, email.

  1. Jumlah alamat email lebih besar dari atau sama dengan jumlah pecahan.
  2. Jumlah baris per alamat email serupa (dalam kasus kami, tepat satu baris per alamat karena kami menyatakan email kunci).

Setiap pilihan tabel dan kolom distribusi tempat salah satu properti gagal akan berakhir dengan ukuran data yang tidak merata pada pekerja, yaitu, penyimpangan data.

Menambahkan batasan ke data terdistribusi

Menggunakan Azure Cosmos DB for PostgreSQL memungkinkan Anda untuk terus menikmati keamanan database relasional, termasuk batasan database. Namun, ada batasannya. Karena sifat sistem terdistribusi, Azure Cosmos DB for PostgreSQL tidak akan merujuk silang batasan keunikan atau integritas referensial antara simpul pekerja.

Mari mempertimbangkan contoh tabel users dengan tabel terkait.

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

Untuk efisiensi, kami mendistribusikan books dengan cara yang sama seperti users: dengan alamat email pemilik. Mendistribusikan menurut nilai kolom serupa disebut kolokasi.

Kami tidak memiliki masalah mendistribusikan buku dengan kunci asing kepada pengguna, karena kuncinya ada di kolom distribusi. Namun, kami akan kesulitan membuat kunci untuk isbn:

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

Dalam tabel terdistribusi yang terbaik yang dapat kami lakukan adalah membuat kolom distribusi untuk kolom modulo unik:

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

Batasan di atas hanya membuat isbn unik per pengguna. Pilihan lain adalah membuat tabel referensi untuk buku daripada tabel terdistribusi, dan membuat tabel terdistribusi terpisah yang mengaitkan buku dengan pengguna.

Mengkueri tabel terdistribusi

Di bagian sebelumnya, kami melihat bagaimana baris tabel terdistribusi ditempatkan dalam pecahan pada simpul pekerja. Sebagian besar waktu Anda tidak perlu tahu bagaimana atau di mana data disimpan dalam kluster. Azure Cosmos DB for PostgreSQL memiliki pelaksana kueri terdistribusi yang secara otomatis membagi kueri SQL reguler. Ini menjalankannya secara paralel pada simpul pekerja yang dekat dengan data.

Misalnya, kami dapat menjalankan kueri untuk menemukan usia rata-rata pengguna, memperlakukan tabel users terdistribusi seperti tabel normal pada koordinator.

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

kueri akan membuka pecahan melalui koordinator

Di balik layar, eksekutor Azure Cosmos DB for PostgreSQL membuat kueri terpisah untuk setiap shard, menjalankannya pada pekerja, dan menggabungkan hasilnya. Anda dapat melihatnya jika menggunakan perintah 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)

Output menunjukkan contoh rencana eksekusi untuk fragmen kueri yang berjalan pada pecahan 102040 (tabel users_102040 pada pekerja 10.0.0.21). Fragmen lain tidak ditampilkan karena mirip. Kami dapat melihat bahwa simpul pekerja memindai tabel pecahan dan menerapkan agregat. Simpul koordinator menggabungkan agregat untuk hasil akhir.

Langkah berikutnya

Dalam tutorial ini, kami membuat tabel terdistribusi, dan mempelajari tentang pecahan dan penempatannya. Kami melihat tantangan menggunakan keunikan dan batasan kunci asing, dan akhirnya melihat bagaimana kueri yang didistribusikan bekerja pada tingkat tinggi.