Di Postgres-XL, urutan dipertahankan di Manajer Transaksi Global (GTM) untuk memastikan bahwa mereka diberi nilai yang tidak bertentangan ketika mereka bertambah dari beberapa node. Ini menambah overhead yang signifikan untuk kueri yang melakukan ribuan INSERT dalam tabel dengan kolom serial, menambah urutan satu per satu dan membuat jaringan bolak-balik ke GTM, untuk setiap INSERT.
Shaun Thomas di blog baru-baru ini mengeluh tentang INSERT yang berjalan lebih lambat di Postgres-XL dibandingkan dengan vanilla PostgreSQL. Sudah ada cara untuk meningkatkan kinerja untuk urutan, tetapi itu jelas tidak diiklankan dengan baik. Saya pikir ini adalah kesempatan yang baik untuk menjelaskan fasilitasnya.
Postgres-XL menyediakan GUC yang dapat diatur pengguna yang disebut sequence_range . Setiap backend meminta blok nilai urutan yang dikontrol oleh GUC ini. Mengingat bahwa COPY populer digunakan untuk memuat data secara massal di Postgres, Postgres-XL secara otomatis menimpa GUC ini selama operasi COPY dan menyetelnya ke 1000, sehingga secara dramatis meningkatkan kinerja COPY. Sayangnya, untuk INSERT biasa, defaultnya adalah 1 dan kecuali pengguna secara eksplisit menetapkan sequence_range ke nilai yang cukup tinggi, kinerja INSERT menderita. Berikut ini contohnya, menggunakan skema sampel yang sama seperti yang digunakan oleh Shaun di postingan blognya.
CREATE TABLE sensor_log ( sensor_log_id SERIAL PRIMARY KEY, location VARCHAR NOT NULL, reading BIGINT NOT NULL, reading_date TIMESTAMP NOT NULL ) DISTRIBUTE BY HASH (sensor_log_id); postgres=# \timing Timing is on. postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 12067.911 ms postgres=# set sequence_range TO 1000; SET Time: 1.231 ms postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 397.406 ms
Jadi dengan menyetel sequence_range dengan tepat hingga 1000, kinerja kueri INSERT meningkat hampir 30 kali lipat.
Ketika fitur ini ditambahkan, nilai default sequence_range GUC disetel ke 1 karena dapat meninggalkan lubang pada nilai sequence. Tetapi melihat implikasi kinerja untuk kasus penggunaan yang sangat umum, kami memutuskan untuk meningkatkan default ke 1000 dan ini sekarang telah dikomit ke cabang XL9_5_STABLE dari repositori.
Penting untuk dicatat bahwa meskipun nilai sequence_range high yang tinggi akan meningkatkan kinerja untuk urutan dan serial, juga dapat meninggalkan lubang besar dalam rentang urutan karena rentang urutan di-cache di tingkat backend. Untuk mengatasi masalah ini, Postgres-XL memulai dengan nilai parameter CACHE yang ditentukan yang digunakan pada waktu pembuatan urutan dan menggandakannya setiap kali (dibatasi oleh sequence_range) jika urutan dikonsumsi pada tingkat yang sangat tinggi.
Peningkatan serupa juga dapat dicapai dengan meningkatkan nilai parameter CACHE dari urutan sehingga potongan nilai urutan di-cache di tingkat backend. Contoh berikut menunjukkan bagaimana melakukannya untuk kolom serial. Tapi sequence_range GUC menyediakan cara mudah untuk mengganti default global dan juga memastikan bahwa urutan di-cache hanya ketika mereka bertambah dengan sangat cepat.
postgres=# ALTER SEQUENCE sensor_log_sensor_log_id_seq CACHE 1000; ALTER SEQUENCE Time: 8.683 ms postgres=# SET sequence_range TO 1; SET Time: 2.341 ms postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 418.068 ms
Anda dapat memilih salah satu dari teknik ini untuk meningkatkan kinerja. Meskipun sekarang nilai default sequence_range diubah menjadi 1000, tidak banyak pengguna yang melihat perbedaan kinerja.