PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

PostgreSQL 9.6:Quét tuần tự song song

Trong một thời gian dài, một trong những thiếu sót được biết đến nhiều nhất của PostgreSQL là khả năng song song hóa các truy vấn. Với việc phát hành phiên bản 9.6, điều này sẽ không còn là vấn đề nữa. Một công việc tuyệt vời đã được thực hiện đối với chủ đề này, bắt đầu từ cam kết 80558c1, việc giới thiệu quét tuần tự song song, chúng ta sẽ thấy trong quá trình của bài viết này.

Đầu tiên, bạn phải lưu ý:sự phát triển của tính năng này diễn ra liên tục và một số tham số đã thay đổi tên giữa một cam kết và một cam kết khác. Bài viết này đã được viết bằng cách sử dụng thanh toán được thực hiện vào ngày 17 tháng 6 và một số tính năng được minh họa ở đây sẽ chỉ có trong phiên bản 9.6 beta2.

So với bản phát hành 9.5, các thông số mới đã được giới thiệu bên trong tệp cấu hình. Đây là:

  • max_parallel_workers_per_gather :số lượng công nhân có thể hỗ trợ quét tuần tự một bảng;
  • min_parallel_relation_size :quy mô tối thiểu mà một mối quan hệ phải có để người lập kế hoạch xem xét việc sử dụng thêm nhân công;
  • llel_setup_cost :thông số lập kế hoạch ước tính chi phí khởi tạo một nhân công;
  • llel_tuple_cost :tham số lập kế hoạch ước tính chi phí chuyển một bộ từ công nhân này sang công nhân khác;
  • force_parallel_mode :tham số hữu ích để thử nghiệm, tính song song mạnh mẽ và cũng là một truy vấn mà trong đó người lập kế hoạch sẽ hoạt động theo những cách khác.

Hãy xem cách sử dụng các nhân viên bổ sung để tăng tốc các truy vấn của chúng tôi. Chúng tôi tạo một bảng kiểm tra với trường INT và một trăm triệu bản ghi:

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 có max_parallel_workers_per_gather được đặt thành 2 theo mặc định, hai công nhân sẽ được kích hoạt trong quá trình quét tuần tự.

Quét tuần tự đơn giản không đưa ra bất kỳ tính mới nào:

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)

Trên thực tế, sự hiện diện của WHERE mệnh đề được yêu cầu để song song hóa:

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)

Chúng ta có thể quay lại hành động trước đó và quan sát cài đặt khác biệt max_parallel_workers_per_gather thành 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)

Một thời gian lớn hơn 2,5 lần.

Người lập kế hoạch không phải lúc nào cũng coi việc quét tuần tự song song là lựa chọn tốt nhất. Nếu một truy vấn không đủ chọn lọc và có nhiều bộ giá trị để chuyển từ worker này sang worker khác, thì nó có thể thích quét tuần tự "cổ điển" hơn:

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)

Trên thực tế, nếu chúng ta cố gắng bắt buộc quét tuần tự song song, chúng ta sẽ nhận được kết quả tồi tệ hơn:

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)

Số lượng công nhân có thể được tăng lên đến max_worker_processes (mặc định:8). Chúng tôi khôi phục giá trị của parallel_tuple_cost và chúng tôi thấy điều gì sẽ xảy ra bằng cách tăng max_parallel_workers_per_gather đến 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)

Mặc dù PostgreSQL có thể sử dụng tới 8 công nhân, nhưng nó chỉ khởi tạo được sáu. Điều này là do Postgres cũng tối ưu hóa số lượng nhân công theo kích thước của bảng và min_parallel_relation_size . Số lượng công nhân do bưu điện cung cấp dựa trên một tiến trình hình học với 3 là tỷ lệ chung 3 và min_parallel_relation_size như yếu tố quy mô. Đây là một ví dụ. Xem xét 8MB của tham số mặc định:

Kích thước Công nhân
<8MB 0
<24MB 1
<72MB 2
<216MB 3
<648MB 4
<1944MB 5
<5822MB 6

Kích thước bảng của chúng tôi là 3458MB, vì vậy 6 là số lượng công nhân hiện có tối đa.

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

Cuối cùng, tôi sẽ trình bày ngắn gọn về những cải tiến đạt được thông qua bản vá này. Chạy truy vấn của chúng tôi với số lượng ngày càng tăng của công nhân, chúng tôi thu được các kết quả sau:

Công nhân Thời gian
0 24767,848 mili giây
1 14855,961 mili giây
2 10415,661 mili giây
3 8041,187 mili giây
4 8090,855 mili giây
5 8082,937 mili giây
6 8061,939 mili giây

Chúng tôi có thể thấy rằng thời gian cải thiện đáng kể, cho đến khi bạn đạt được một phần ba giá trị ban đầu. Cũng có thể giải thích đơn giản rằng chúng ta không thấy sự cải thiện giữa việc sử dụng 3 và 6 công nhân:máy chạy thử nghiệm có 4 CPU nên kết quả ổn định sau khi thêm 3 công nhân nữa vào quy trình ban đầu. .

Cuối cùng, PostgreSQL 9.6 đã tạo tiền đề cho song song hóa truy vấn, trong đó quét tuần tự song song chỉ là kết quả tuyệt vời đầu tiên. Chúng ta cũng sẽ thấy rằng trong 9.6, các tổng hợp đã được song song hóa, nhưng đó là thông tin cho một bài báo khác sẽ được phát hành trong những tuần tới!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chức năng cửa sổ Postgres và nhóm theo ngoại lệ

  2. CTE đệ quy nối các trường với cha mẹ từ điểm tùy ý

  3. Khi nào thì chọn khóa và mở khóa cập nhật?

  4. PG ::DuplicateTable:ERROR:các bài đăng liên quan đã tồn tại

  5. Làm thế nào để chọn mảng 1d từ mảng 2d?