PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Kinerja Urutan dan Serial di Postgres-XL

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.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dukungan SQLAlchemy dari Skema Postgres

  2. Bagaimana cara saya melemparkan string ke integer dan memiliki 0 jika terjadi kesalahan dalam pemeran dengan PostgreSQL?

  3. Jumlah baris di postgresql

  4. Manfaat PostgreSQL

  5. Masalah saat mengimpor file txt ke postgres menggunakan php