Ekstensi sequential_uuid menyediakan dua generator UUID yang menghasilkan pola sekuensial, sehingga membantu mengurangi masalah I/O acak akibat penggunaan UUID yang sepenuhnya acak.
Penerapan
Versi PolarDB for PostgreSQL berikut didukung:
PostgreSQL 18 (versi mesin minor 2.0.18.1.2.0 dan yang lebih baru)
PostgreSQL 17 (versi mesin minor 2.0.17.6.4.0 dan yang lebih baru)
PostgreSQL 16 (versi mesin minor 2.0.16.9.9.0 dan yang lebih baru)
PostgreSQL 15 (versi mesin minor 2.0.15.14.6.0 dan yang lebih baru)
PostgreSQL 14 (versi mesin minor 2.0.14.5.1.0 dan yang lebih baru)
PostgreSQL 11 (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. Masalah ini tidak signifikan pada indeks kecil, namun rasio hit cache turun drastis 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 paling kanan indeks karena nilai sekuens baru lebih besar daripada nilai sebelumnya dan timestamp meningkat secara monoton, 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 berurutan, 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 sepanjang 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 dari UUID berkurang dari 16 byte menjadi 8 byte. Timestamp juga mengurangi keacakan dengan cara yang 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.
Membengkaknya indeks: Jika nilai meningkat secara monoton, indeks dapat membengkak 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 ditentukan oleh 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 pembuatan UUID
Ekstensi `sequential_uuid` menyediakan dua fungsi yang menghasilkan UUID dengan pola sekuensial—satu menggunakan sekuens dan satu lagi menggunakan timestamp.
Fungsi uuid_sequence_nextval menerima parameter berikut:
Objek sekuens bertipe `regclass`.
Ukuran blok sebagai bilangan bulat (default: 65536).
Jumlah blok sebagai bilangan bulat (default: 65536).
Buat 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 sebagai bilangan bulat (default: 60).
Jumlah blok sebagai bilangan bulat (default: 65536).
Buat 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.