Sebelumnya saya telah menulis blog tentang partisi-bijaksana bergabung di PostgreSQL. Di blog itu, saya telah berbicara tentang teknik pencocokan partisi tingkat lanjut yang memungkinkan penggabungan partisi-bijaksana untuk digunakan dalam lebih banyak kasus. Di blog ini kita akan membahas teknik ini secara detail.
Untuk rekap, teknik pencocokan partisi dasar memungkinkan penggabungan antara dua tabel yang dipartisi dilakukan menggunakan teknik penggabungan partisi jika kedua tabel yang dipartisi memiliki batas partisi yang sama persis, mis. tabel yang dipartisi prt1 dan prt2 dijelaskan di bawah
psql> \d+ prt1
... [output clipped]
Partition key: RANGE (a)
Partitions: prt1_p1 FOR VALUES FROM (0) TO (5000),
prt1_p2 FOR VALUES FROM (5000) TO (15000),
prt1_p3 FOR VALUES FROM (15000) TO (30000)
dan
psql>\d+ prt2
... [ output clipped ]
Partition key: RANGE (b)
Partitions: prt2_p1 FOR VALUES FROM (0) TO (5000),
prt2_p2 FOR VALUES FROM (5000) TO (15000),
prt2_p3 FOR VALUES FROM (15000) TO (30000)
Penggabungan antara prt1 dan prt2 pada kunci partisinya (a) dipecah menjadi gabungan antara partisi yang cocok, yaitu prt1_p1 join prt2_p1, prt1_p2 join prt2_p2 dan prt1_p3 join prt2_p3. Hasil dari ketiga join ini merupakan hasil join antara prt1 dan prt2. Ini memiliki banyak keuntungan seperti yang dibahas di blog saya sebelumnya. Namun, pencocokan partisi dasar tidak dapat menggabungkan dua tabel yang dipartisi dengan batas partisi yang berbeda. Dalam contoh di atas, jika prt1 memiliki partisi tambahan prt1_p4 FOR VALUES FROM (30000) TO (50000), pencocokan partisi dasar tidak akan membantu mengonversi gabungan antara prt1 dan prt2 menjadi gabungan partisi karena tidak memiliki partisi yang sama persis batas.
Banyak aplikasi menggunakan partisi untuk memisahkan data yang digunakan secara aktif dan data basi, teknik yang saya bahas di blog saya yang lain. Data basi akhirnya dihapus dengan menjatuhkan partisi. Partisi baru dibuat untuk mengakomodasi data baru. Penggabungan antara dua tabel yang dipartisi seperti itu sebagian besar akan menggunakan gabungan partisi karena sebagian besar waktu mereka akan memiliki partisi yang cocok. Tetapi ketika partisi aktif ditambahkan ke salah satu tabel ini atau yang basi dihapus, batas partisinya tidak akan cocok sampai tabel lain juga menjalani operasi serupa. Selama interval itu, gabungan antara dua tabel ini tidak akan menggunakan gabungan partisi dan mungkin membutuhkan waktu lebih lama untuk dieksekusi. Kami tidak ingin gabungan yang mengenai basis data selama durasi kecil ini berkinerja buruk karena tidak dapat menggunakan gabungan partisi. Algoritme pencocokan partisi tingkat lanjut membantu dalam kasus ini dan kasus yang lebih rumit di mana batas partisi tidak sama persis.
Algoritme pencocokan partisi tingkat lanjut
Teknik pencocokan partisi tingkat lanjut menemukan partisi yang cocok dari dua tabel yang dipartisi meskipun batas partisinya tidak sama persis. Ia menemukan partisi yang cocok dengan membandingkan batas dari kedua tabel dalam urutan yang diurutkan mirip dengan algoritme penggabungan gabungan. Setiap dua partisi, satu dari masing-masing tabel yang dipartisi, yang batasnya sama persis atau tumpang tindih dianggap sebagai mitra gabungan karena mereka mungkin berisi baris yang bergabung. Melanjutkan contoh di atas, katakanlah partisi baru yang aktif prt2_p4 ditambahkan ke prt4. Tabel yang dipartisi sekarang terlihat seperti:
psql>\d+ prt1
... [output clipped]
Partition key: RANGE (a)
Partitions: prt1_p1 FOR VALUES FROM (0) TO (5000),
prt1_p2 FOR VALUES FROM (5000) TO (15000),
prt1_p3 FOR VALUES FROM (15000) TO (30000)
dan
psql>\d+ prt2
... [ output clipped ]
Partition key: RANGE (b)
Partitions: prt2_p1 FOR VALUES FROM (0) TO (5000),
prt2_p2 FOR VALUES FROM (5000) TO (15000),
prt2_p3 FOR VALUES FROM (15000) TO (30000),
prt2_p4 FOR VALUES FROM (30000) TO (50000)
Sangat mudah untuk melihat bahwa batas partisi prt1_p1 dan prt2_p1, prt1_p2 dan prt2_p2, dan prt1_p3 dan prt2_p3 masing-masing cocok. Tetapi tidak seperti pencocokan partisi dasar, pencocokan partisi lanjutan akan mengetahui bahwa prt2_p4 tidak memiliki partisi yang cocok di prt1. Jika gabungan antara prt1 dan prt2 adalah gabungan INNER atau ketika prt2 adalah relasi INNER dalam gabungan, hasil gabungan tidak akan memiliki baris apa pun dari prt2_p4. Diaktifkan dengan informasi terperinci tentang partisi yang cocok dan partisi yang tidak cocok, sebagai lawan hanya apakah batas partisi cocok atau tidak, pengoptimal kueri dapat memutuskan apakah akan menggunakan penggabungan partisi atau tidak. Dalam hal ini, ia akan memilih untuk mengeksekusi gabungan sebagai gabungan antara partisi yang cocok dengan mengesampingkan prt2_p4. Tapi itu tidak seperti pencocokan partisi "lanjutan". Mari kita lihat kasus yang sedikit lebih rumit menggunakan tabel yang dipartisi daftar kali ini:
psql>\d+ plt1
Partition key: LIST (c)
Partitions: plt1_p1 FOR VALUES IN ('0001', '0003'),
plt1_p2 FOR VALUES IN ('0004', '0006'),
plt1_p3 FOR VALUES IN ('0008', '0009')
dan
psql>\d+ plt2
Partition key: LIST (c)
Partitions: plt2_p1 FOR VALUES IN ('0002', '0003'),
plt2_p2 FOR VALUES IN ('0004', '0006'),
plt2_p3 FOR VALUES IN ('0007', '0009')
Amati bahwa ada tepat tiga partisi di kedua relasi tetapi daftar nilai partisi berbeda. Daftar yang terkait dengan partisi plt1_p2 sama persis dengan plt2_p2. Selain itu tidak ada dua partisi, satu dari kedua sisi, memiliki daftar yang sama persis. Algoritme pencocokan partisi lanjutan menyimpulkan bahwa plt1_p1 dan plt2_p1 memiliki daftar yang tumpang tindih dan daftarnya tidak tumpang tindih dengan partisi lain dari relasi lain. Demikian pula untuk plt1_p3 dan plt2_p3. Pengoptimal kueri kemudian melihat bahwa gabungan antara plt1 dan plt2 dapat dijalankan sebagai gabungan partisi dengan menggabungkan partisi yang cocok, yaitu plt1_p1 dan plt2_p1, plt1_p2, dan plt2_p2, serta plt1_p3 dan plt2_p3. Algoritme dapat menemukan partisi yang cocok dalam kumpulan daftar terikat partisi yang lebih kompleks serta tabel yang dipartisi rentang. Tapi kami tidak akan membahasnya demi singkatnya. Pembaca yang tertarik dan lebih berani dapat melihat komit. Ini juga memiliki banyak kasus uji, yang menunjukkan berbagai skenario di mana algoritma pencocokan partisi lanjutan digunakan.
Batasan
Penggabungan luar dengan partisi yang cocok hilang di sisi dalam
Gabungan luar menimbulkan masalah khusus di dunia PostgreSQL. Pertimbangkan prt2 LEFT JOIN prt1, dalam contoh di atas, di mana prt2 adalah relasi OUTER. prt2_p4 tidak memiliki partner penggabung di prt1 namun baris di partisi tersebut harus menjadi bagian dari hasil penggabungan karena termasuk dalam relasi luar. Di PostgreSQL ketika sisi INNER dari gabungan kosong, itu diwakili oleh relasi "dummy" yang tidak memancarkan baris tetapi masih mengetahui skema relasi itu. Biasanya relasi "dummy" muncul dari relasi non-dummy yang tidak akan mengeluarkan baris apa pun karena beberapa optimasi kueri seperti pengecualian batasan. Pengoptimal kueri PostgreSQL menandai hubungan non-dummy seperti dummy dan eksekutor melanjutkan secara normal saat mengeksekusi gabungan semacam itu. Tetapi ketika tidak ada partisi dalam yang cocok untuk partisi luar, tidak ada "entitas yang ada" yang dapat ditandai sebagai "dummy". Misalnya, dalam hal ini tidak ada prt1_p4 yang dapat mewakili partisi dalam dummy yang bergabung dengan prt2_p4 luar. Saat ini, PostgreSQL tidak memiliki cara untuk "membuat" hubungan "bodoh" seperti itu selama perencanaan. Oleh karena itu, pengoptimal kueri tidak menggunakan penggabungan partisi dalam kasus ini.
Idealnya penggabungan seperti itu dengan bagian dalam yang kosong hanya membutuhkan skema hubungan bagian dalam dan bukan keseluruhan hubungan. Skema ini dapat diturunkan dari tabel yang dipartisi itu sendiri. Yang dibutuhkan hanyalah kemampuan untuk menghasilkan baris gabungan dengan menggunakan kolom dari baris di sisi luar yang digabungkan dengan nilai NULL untuk kolom dari sisi dalam. Setelah kami memiliki kemampuan itu di PostgreSQL, pengoptimal kueri akan dapat menggunakan penggabungan partisi-bijaksana bahkan dalam kasus ini.
Izinkan saya menekankan bahwa gabungan luar di mana tidak ada partisi yang hilang pada gabungan dalam menggunakan gabungan partisi.
Beberapa partisi yang cocok
Ketika tabel dipartisi sedemikian rupa sehingga beberapa partisi dari satu sisi cocok dengan satu atau lebih partisi di sisi lain, partisi-bijaksana bergabung tidak dapat digunakan karena tidak ada cara untuk menginduksi hubungan "Tambah" selama waktu perencanaan yang mewakili dua atau lebih partisi bersama. Mudah-mudahan kami juga akan menghapus batasan itu kapan-kapan dan mengizinkan penggabungan partisi-bijaksana untuk digunakan dalam kasus-kasus itu juga.
Hash tabel yang dipartisi
Batas partisi dari dua tabel yang dipartisi hash menggunakan modulo yang sama selalu cocok. Ketika modulo berbeda, sebuah baris dari partisi tertentu dari satu tabel mungkin memiliki mitra yang bergabung di banyak partisi yang lain, sehingga partisi yang diberikan dari satu sisi cocok dengan beberapa partisi dari tabel lain sehingga membuat penggabungan partisi tidak efektif.
Ketika algoritma pencocokan partisi lanjutan gagal menemukan partisi yang cocok atau penggabungan partisi tidak dapat digunakan karena batasan di atas, PostgreSQL mundur untuk bergabung dengan tabel yang dipartisi sebagai tabel biasa.
Waktu pencocokan partisi lanjutan
Simon mengemukakan poin menarik ketika berkomentar tentang fitur tersebut. Partisi dari tabel yang dipartisi tidak sering berubah sehingga hasil pencocokan partisi lanjutan akan tetap sama untuk durasi yang lebih lama. Menghitungnya setiap kali kueri yang melibatkan tabel ini dieksekusi tidak diperlukan. Sebagai gantinya, kita dapat menyimpan set partisi yang cocok di beberapa katalog dan menyegarkannya setiap kali partisi berubah. Itu adalah beberapa pekerjaan tetapi sepadan dengan waktu yang dihabiskan untuk mencocokkan partisi untuk setiap kueri.
Bahkan dengan semua keterbatasan ini, apa yang kita miliki saat ini adalah solusi yang sangat berguna yang melayani sebagian besar kasus praktis. Tak perlu dikatakan bahwa fitur ini bekerja secara mulus dengan FDW join push down meningkatkan kemampuan sharding yang sudah dimiliki PostgreSQL!