Ekstensi sequential_uuid menyediakan dua generator UUID sekuensial untuk mengurangi permasalahan I/O acak yang disebabkan oleh generator UUID sepenuhnya acak.
Lingkup
Versi PolarDB for PostgreSQL (Compatible with Oracle) berikut ini didukung:
Oracle syntax compatibility 2.0 (versi mesin minor 2.0.14.5.1.0 dan yang lebih baru)
Oracle syntax compatibility 1.0 (versi mesin minor 2.0.11.9.28.0 dan yang lebih baru)
Anda dapat melihat nomor versi mesin minor di Konsol, atau dengan menjalankan pernyataan SHOW polardb_version;. Jika persyaratan versi mesin minor tidak terpenuhi, Anda harus upgrade the minor engine version.
Informasi latar belakang
Generator UUID acak standar memilih nilai secara seragam dari rentang tertentu. Hal ini menyebabkan lokalitas data yang buruk saat memasukkan data ke dalam indeks karena semua halaman daun indeks memiliki kemungkinan yang sama untuk diakses, sehingga seluruh indeks mungkin perlu dimuat ke dalam memori. Permasalahan ini tidak muncul pada indeks kecil, namun rasio hit cache akan menurun cepat begitu ukuran indeks melebihi kapasitas shared buffer atau RAM.
Berbeda dengan UUID acak, UUID berbasis sekuens dan timestamp memiliki pola sekuensial. Pola ini memastikan bahwa data baru hampir selalu dimasukkan di tepi kanan indeks karena nilai sekuens baru lebih besar daripada nilai sebelumnya dan timestamp meningkat secara monotonik, sehingga membantu meningkatkan rasio hit cache.
Generator UUID dengan pola sekuensial meningkatkan prediktabilitas UUID dan probabilitas tabrakan lintas mesin.
Untuk informasi lebih lanjut mengenai manfaat UUID sekuensial, lihat Sequential UUID Generators.
Tujuan utama sequential_uuid adalah menghasilkan UUID yang lebih sekuensial tanpa mengurangi keacakan secara signifikan, karena pengurangan keacakan dapat meningkatkan probabilitas tabrakan dan prediktabilitas UUID.
Desain generator
Cara paling sederhana untuk membuat UUID lebih sekuensial adalah menggunakan nilai sekuensial sebagai awalan. Misalnya, Anda dapat mengambil nilai dari sekuens atau timestamp dan menambahkan data acak untuk membentuk UUID 16 byte. Metode ini menghasilkan UUID yang hampir sepenuhnya sekuensial, tetapi memiliki dua masalah:
Berkurangnya keacakan: Jika Anda menggunakan sekuens yang menghasilkan nilai `bigint`, bagian acak UUID berkurang dari 16 byte menjadi 8 byte. Timestamp juga mengurangi keacakan dengan cara serupa, tergantung pada presisinya. Pengurangan keacakan ini meningkatkan probabilitas tabrakan dan prediktabilitas UUID. Sebagai contoh, Anda dapat menentukan UUID mana yang dihasilkan dalam waktu berdekatan bahkan menginferensi timestamp spesifiknya.
Pembengkakan (bloat): Jika nilai-nilai tersebut meningkat secara monotonik, indeks dapat mengalami pembengkakan setelah data historis dihapus. Contoh umumnya adalah indeks berdasarkan timestamp pada tabel log.
Untuk mengatasi masalah ini, generator `sequential_uuid` dirancang agar melakukan loopback secara berkala. Loopback dapat terjadi setelah jumlah UUID tertentu dihasilkan atau setelah interval waktu tertentu. Dalam kedua kasus tersebut, UUID dihasilkan dalam blok dengan format (block ID; random data). Ukuran block ID bersifat tetap dan bergantung pada jumlah blok, yang merupakan parameter generator. Sebagai contoh, jika Anda menggunakan nilai default 65.536 blok, block ID memerlukan 2 byte. Block ID meningkat pada setiap blok dan akhirnya melakukan loopback.
Generator UUID berbasis sekuens dapat menggunakan blok yang masing-masing berisi 256 UUID. Block ID 2 byte dihitung sebagai berikut:
(nextval('s') / 256) % 65536CatatanGenerator melakukan loopback setiap kali 16.777.216 (256 × 65.536) UUID dihasilkan.
Ukuran blok didefinisikan berdasarkan jumlah UUID yang dikandungnya.
Generator UUID berbasis timestamp memiliki nilai default 65.536 blok, sama seperti generator berbasis sekuens. Block ID dihitung sebagai berikut:
(timestamp / 60) % 65536CatatanGenerator melakukan loopback kira-kira setiap 45 hari.
Ukuran blok didefinisikan sebagai interval waktu. Nilai default-nya adalah 60 detik.
Fungsi pembangkit UUID
Ekstensi `sequential_uuid` menyediakan dua fungsi yang menghasilkan UUID dengan pola sekuensial: satu berbasis sekuens dan satu berbasis timestamp.
Fungsi uuid_sequence_nextval menerima parameter berikut:
Objek sekuens bertipe `regclass`.
Ukuran blok dalam bentuk integer (default: 65536).
Jumlah blok dalam bentuk integer (default: 65536).
Contoh pembuatan UUID dengan pola sekuensial menggunakan sekuens:
CREATE EXTENSION sequential_uuids; CREATE SEQUENCE s; SELECT uuid_sequence_nextval('s'::regclass, 256, 65536);Hasilnya sebagai berikut:
uuid_sequence_nextval -------------------------------------- 00005547-8a67-452d-bdf7-b390f1edc49b (1 row)Fungsi uuid_time_nextval menerima parameter berikut:
Interval waktu dalam detik (default: 60).
Jumlah blok dalam bentuk integer (default: 65536).
Contoh pembuatan UUID dengan pola sekuensial menggunakan timestamp:
CREATE EXTENSION sequential_uuids; SELECT uuid_time_nextval(1, 256);Hasil berikut dikembalikan:
uuid_time_nextval -------------------------------------- 08dac705-8776-4ce3-a45c-123fd65e11e8 (1 row)
Nilai default untuk parameter-parameter ini cocok untuk sebagian besar skenario.