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

PostgreSQL 9.6:Pemindaian Sekuensial Paralel

Untuk waktu yang lama, salah satu kekurangan PostgreSQL yang paling terkenal adalah kemampuan untuk memparalelkan kueri. Dengan rilis versi 9.6, ini tidak akan menjadi masalah lagi. Pekerjaan yang bagus telah dilakukan dalam hal ini, mulai dari commit 80558c1, pengenalan pemindaian sekuensial paralel, yang akan kita lihat dalam artikel ini.

Pertama, Anda harus memperhatikan:pengembangan fitur ini terus menerus dan beberapa parameter telah berganti nama antara komit dan komit lainnya. Artikel ini ditulis menggunakan checkout yang diambil pada 17 Juni dan beberapa fitur yang diilustrasikan di sini hanya akan hadir dalam versi 9.6 beta2.

Dibandingkan dengan rilis 9.5, parameter baru telah diperkenalkan di dalam file konfigurasi. Ini adalah:

  • max_parallel_workers_per_gather :jumlah pekerja yang dapat membantu pemindaian tabel secara berurutan;
  • min_parallel_relation_size :ukuran minimum yang harus dimiliki suatu relasi agar perencana mempertimbangkan penggunaan pekerja tambahan;
  • parallel_setup_cost :parameter perencana yang memperkirakan biaya instantiate seorang pekerja;
  • parallel_tuple_cost :parameter perencana yang memperkirakan biaya transfer tuple dari satu pekerja ke pekerja lain;
  • force_parallel_mode :parameter yang berguna untuk pengujian, paralelisme yang kuat, dan juga kueri di mana perencana akan beroperasi dengan cara lain.

Mari kita lihat bagaimana pekerja tambahan dapat digunakan untuk mempercepat kueri kita. Kami membuat tabel pengujian dengan bidang INT dan seratus juta catatan:

postgres=# CREATE TABLE test (i int);
CREATE TABLE
postgres=# INSERT INTO test SELECT generate_series(1,100000000);
INSERT 0 100000000
postgres=# ANALYSE test;
ANALYZE

PostgreSQL memiliki max_parallel_workers_per_gather diatur ke 2 secara default, di mana dua pekerja akan diaktifkan selama pemindaian berurutan.

Pemindaian sekuensial sederhana tidak menghadirkan hal baru:

postgres=# EXPLAIN ANALYSE SELECT * FROM test;
                                                       QUERY PLAN                         
------------------------------------------------------------------------------------------------------------------------
 Seq Scan on test  (cost=0.00..1442478.32 rows=100000032 width=4) (actual time=0.081..21051.918 rows=100000000 loops=1)
 Planning time: 0.077 ms
 Execution time: 28055.993 ms
(3 rows)

Bahkan, kehadiran WHERE klausa diperlukan untuk paralelisasi:

postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..964311.60 rows=1 width=4) (actual time=3.381..9799.942 rows=1 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on test  (cost=0.00..963311.50 rows=0 width=4) (actual time=6525.595..9791.066 rows=0 loops=3)
         Filter: (i = 1)
         Rows Removed by Filter: 33333333
 Planning time: 0.130 ms
 Execution time: 9804.484 ms
(8 rows)

Kita dapat kembali ke tindakan sebelumnya dan mengamati perbedaan pengaturan max_parallel_workers_per_gather ke 0:

postgres=# SET max_parallel_workers_per_gather TO 0;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
                                               QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Seq Scan on test  (cost=0.00..1692478.40 rows=1 width=4) (actual time=0.123..25003.221 rows=1 loops=1)
   Filter: (i = 1)
   Rows Removed by Filter: 99999999
 Planning time: 0.105 ms
 Execution time: 25003.263 ms
(5 rows)

Waktu 2,5 kali lebih besar.

Perencana tidak selalu menganggap pemindaian sekuensial paralel sebagai pilihan terbaik. Jika kueri tidak cukup selektif dan ada banyak tupel untuk ditransfer dari pekerja ke pekerja, mungkin lebih memilih pemindaian sekuensial "klasik":

postgres=# SET max_parallel_workers_per_gather TO 2;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i<90000000;
                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
 Seq Scan on test  (cost=0.00..1692478.40 rows=90116088 width=4) (actual time=0.073..31410.276 rows=89999999 loops=1)
   Filter: (i < 90000000)
   Rows Removed by Filter: 10000001
 Planning time: 0.133 ms
 Execution time: 37939.401 ms
(5 rows)

Faktanya, jika kita mencoba untuk memaksa pemindaian sekuensial paralel, kita mendapatkan hasil yang lebih buruk:

postgres=# SET parallel_tuple_cost TO 0;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i<90000000;
                                                             QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..964311.50 rows=90116088 width=4) (actual time=0.454..75546.078 rows=89999999 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   ->  Parallel Seq Scan on test  (cost=0.00..1338795.20 rows=37548370 width=4) (actual time=0.088..20294.670 rows=30000000 loops=3)
         Filter: (i < 90000000)
         Rows Removed by Filter: 3333334
 Planning time: 0.128 ms
 Execution time: 83423.577 ms
(8 rows)

Jumlah pekerja dapat ditingkatkan hingga max_worker_processes (standar:8). Kami mengembalikan nilai parallel_tuple_cost dan kami melihat apa yang terjadi dengan meningkatkan max_parallel_workers_per_gather ke 8.

postgres=# SET parallel_tuple_cost TO DEFAULT ;
SET
postgres=# SET max_parallel_workers_per_gather TO 8;
SET
postgres=# EXPLAIN ANALYZE SELECT * FROM test WHERE i=1;
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..651811.50 rows=1 width=4) (actual time=3.684..8248.307 rows=1 loops=1)
   Workers Planned: 6
   Workers Launched: 6
   ->  Parallel Seq Scan on test  (cost=0.00..650811.40 rows=0 width=4) (actual time=7053.761..8231.174 rows=0 loops=7)
         Filter: (i = 1)
         Rows Removed by Filter: 14285714
 Planning time: 0.124 ms
 Execution time: 8250.461 ms
(8 rows)

Meskipun PostgreSQL dapat menggunakan hingga 8 pekerja, PostgreSQL hanya menggunakan enam. Ini karena Postgres juga mengoptimalkan jumlah pekerja sesuai dengan ukuran tabel dan min_parallel_relation_size . Jumlah pekerja yang disediakan oleh postgres didasarkan pada perkembangan geometris dengan 3 sebagai rasio umum 3 dan min_parallel_relation_size sebagai faktor skala. Berikut adalah contoh. Mempertimbangkan 8MB parameter default:

Ukuran Pekerja
<8MB 0
<24MB 1
<72MB 2
<216MB 3
<648MB 4
<1944MB 5
<5822MB 6

Ukuran meja kami adalah 3458MB, jadi 6 adalah jumlah maksimum pekerja yang tersedia.

postgres=# \dt+ test
                    List of relations
 Schema | Name | Type  |  Owner   |  Size   | Description
--------+------+-------+----------+---------+-------------
 public | test | table | postgres | 3458 MB |
(1 row)

Akhirnya, saya akan memberikan demonstrasi singkat tentang peningkatan yang dicapai melalui patch ini. Menjalankan kueri kami dengan jumlah pekerja yang terus bertambah, kami memperoleh hasil berikut:

Pekerja Waktu
0 24767.848 md
1 14855.961 md
2 10415.661 md
3 8041.187 md
4 8090.855 md
5 8082.937 md
6 8061.939 md

Kita dapat melihat bahwa waktu meningkat secara dramatis, sampai Anda mencapai sepertiga dari nilai awal. Juga sederhana untuk menjelaskan fakta bahwa kami tidak melihat peningkatan antara penggunaan 3 dan 6 pekerja:mesin tempat pengujian dijalankan memiliki 4 CPU, sehingga hasilnya stabil setelah menambahkan 3 pekerja lagi ke proses awal .

Terakhir, PostgreSQL 9.6 telah menetapkan tahapan untuk paralelisasi kueri, di mana pemindaian sekuensial paralel hanya merupakan hasil pertama yang bagus. Kita juga akan melihat bahwa di 9.6, agregasi telah diparalelkan, tetapi itu adalah informasi untuk artikel lain yang akan dirilis dalam beberapa minggu mendatang!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penyelaman Cloud Vendor:PostgreSQL di Google Cloud Platform (GCP)

  2. Tidak dapat terhubung ke server postgres di buruh pelabuhan dari aplikasi buruh pelabuhan

  3. PostgreSQL JDBC Null String diambil sebagai byte

  4. Cara Menyisipkan ke dalam Array di PostgreSQL

  5. Bagaimana cara mempercepat penghitungan baris dalam tabel PostgreSQL?