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

Cách tận dụng các tính năng phân vùng mới trong PostgreSQL 11

Phân vùng là gì?

Phân vùng chia các bảng lớn thành các phần nhỏ hơn, giúp tăng hiệu suất truy vấn, làm cho các nhiệm vụ bảo trì dễ dàng hơn, cải thiện hiệu quả lưu trữ dữ liệu và sao lưu cơ sở dữ liệu nhanh hơn. Bạn có thể đọc thêm về phân vùng PostgreSQL trong blog của chúng tôi “Hướng dẫn phân vùng dữ liệu trong PostgreSQL”.

Với bản phát hành gần đây của PostgreSQL 11, có rất nhiều tính năng phân vùng mới tuyệt vời. Chi tiết về các tính năng phân vùng mới này sẽ được đề cập trong blog này cùng với một số ví dụ về mã.

Cập nhật các khóa phân vùng

Trước PostgreSQL 11, câu lệnh Cập nhật thay đổi giá trị của khóa phân vùng bị hạn chế và không được phép. Điều này hiện có thể thực hiện được trong phiên bản mới. Câu lệnh cập nhật có thể thay đổi giá trị của khóa phân vùng; nó thực sự di chuyển các hàng đến bảng phân vùng chính xác. Về cơ bản, nó thực hiện XÓA KHỎI phân vùng cũ và CHÈN vào phân vùng mới (XÓA + CHÈN).

Được rồi, hãy kiểm tra điều này. Tạo bảng và xác minh cách hoạt động của bản cập nhật trên khóa phân vùng.

CREATE TABLE customers(cust_id bigint NOT NULL,cust_name varchar(32) NOT NULL,cust_address text,
cust_country text)PARTITION BY LIST(cust_country);
CREATE TABLE customer_ind PARTITION OF customers FOR VALUES IN ('ind');
CREATE TABLE customer_jap PARTITION OF customers FOR VALUES IN ('jap');
CREATE TABLE customers_def PARTITION OF customers DEFAULT;
severalnines_v11=# INSERT INTO customers VALUES (2039,'Puja','Hyderabad','ind');
INSERT 0 1
severalnines_v11=#  SELECT * FROM customer_ind;
 cust_id | cust_name | cust_address | cust_country
  2039 | Puja      | Hyderabad    | ind
(1 row)
severalnines_v11=# UPDATE customers SET cust_country ='jap' WHERE cust_id=2039;
UPDATE 1
--  it moved the row to correct  partition table.
severalnines_v11=# SELECT * FROM customer_ind;
 cust_id | cust_name | cust_address | cust_country
---------+-----------+--------------+--------------
(0 rows)
severalnines_v11=# SELECT * FROM customer_jap;
 cust_id | cust_name | cust_address | cust_country
---------+-----------+--------------+--------------
    2039 | Puja      | Hyderabad    | jap
(1 row)

Thận trọng:CẬP NHẬT sẽ xảy ra lỗi nếu không có bảng phân vùng mặc định và các giá trị cập nhật không khớp với tiêu chí phân vùng trong bất kỳ bảng con nào.

severalnines_v11=#  UPDATE customers1 SET cust_country ='ypp' WHERE cust_id=2039;
2018-11-21 00:13:54.901 IST [1479] ERROR:  no partition of relation "customers1" found for row
2018-11-21 00:13:54.901 IST [1479] DETAIL:  Partition key of the failing row contains (cust_country) = (ypp).
2018-11-21 00:13:54.901 IST [1479] STATEMENT:  UPDATE customers1 SET cust_country ='ypp' WHERE cust_id=2039;
ERROR:  no partition of relation "customers1" found for row
DETAIL:  Partition key of the failing row contains (cust_country) = (ypp).
[ -- the value of cust_country was not mapped to any part table so it failed]

Tạo phân vùng mặc định

Tính năng phân vùng PostgreSQL 11 DEFAULT lưu trữ các bộ dữ liệu không ánh xạ đến bất kỳ phân vùng nào khác. Trước PostgreSQL 11, các hàng này sẽ bị lỗi. Một hàng không được ánh xạ tới bất kỳ bảng phân vùng nào sẽ được chèn vào phân vùng mặc định.

Ví dụ trong phòng thí nghiệm:Mã quốc gia `Hoa Kỳ` không được xác định trong bảng phân vùng bên dưới, nhưng nó vẫn được chèn thành công vào bảng mặc định.

CREATE TABLE customers_def PARTITION OF customers DEFAULT;
severalnines_v11=#  INSERT INTO customers VALUES (4499,'Tony','Arizona','USA');
INSERT 0 1
severalnines_v11=#  select * FROM customers_def;
 cust_id | cust_name | cust_address | cust_country
---------+-----------+--------------+--------------
    4499 | Tony      | Arizona      | USA

Lưu ý:Phân vùng mặc định sẽ ngăn bất kỳ sự bổ sung phân vùng mới nào nếu giá trị phân vùng đó tồn tại trong bảng mặc định. Trong trường hợp này, `USA` tồn tại trong phân vùng Mặc định nên nó sẽ không hoạt động như bên dưới.

severalnines_v11=# CREATE TABLE customer_usa PARTITION OF customers FOR VALUES IN ('USA');
2018-11-21 00:46:34.890 IST [1526] ERROR:  updated partition constraint for default partition "customers_def" would be violated by some row
2018-11-21 00:46:34.890 IST [1526] STATEMENT:  CREATE TABLE customer_usa PARTITION OF customers FOR VALUES IN ('USA');ERROR:  updated partition constraint for default partition "customers_def" would be violated by some row
severalnines_v11=#
Resolution - You need to move/remove those rows from Default table, then it will then let you create new part table like below.
severalnines_v11=# DELETE FROM customers_def WHERE cust_country in ('USA'); DELETE 1
severalnines_v11=# CREATE TABLE customer_usa PARTITION OF customers FOR VALUES IN ('USA');
CREATE TABLE
severalnines_v11=#
Nudgets :

Không thể chỉ định phân vùng DEFAULT cho bảng được phân vùng HASH. Không được có nhiều hơn một bảng DEFAULT cho bảng phân vùng.

Phân vùng băm

Đây là một cơ chế phân vùng mới, nếu bạn không thể quyết định về một phạm vi hoặc phân vùng danh sách (vì bạn không chắc chắn kích thước của thùng sẽ lớn như thế nào). Phân vùng băm giải quyết vấn đề phân phối dữ liệu này.

Bảng được phân vùng bằng cách chỉ định một mô đun và phần còn lại cho mỗi phân vùng. Mỗi phân vùng sẽ chứa các hàng mà giá trị băm của khóa phân vùng được chia cho mô-đun được chỉ định sẽ tạo ra phần còn lại được chỉ định. Hàm HASH đảm bảo rằng các hàng sẽ được phân phối gần như đồng đều trong tất cả bảng phân vùng.

Để bắt đầu, bạn cần quyết định số lượng bảng phân vùng được yêu cầu và do đó, mô-đun và phần còn lại có thể được xác định; nếu mô-đun sẽ là 4, phần còn lại chỉ có thể là từ [0-3].

[Modulus - Số lượng bàn | Phần còn lại - Giá trị của phần còn lại chuyển vào nhóm nào]

Cách thiết lập phân vùng băm

-- hash partition
CREATE TABLE part_hash_test (x int, y text) PARTITION BY hash (x);
-- create child partitions
CREATE TABLE part_hash_test_0 PARTITION OF part_hash_test FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE part_hash_test_1 PARTITION OF part_hash_test FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE part_hash_test_2 PARTITION OF part_hash_test FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE part_hash_test_3 PARTITION OF part_hash_test FOR VALUES WITH (MODULUS 4, REMAINDER 3);

Chèn 50k bản ghi trong bảng mẹ:

severalnines_v11=# INSERT INTO part_hash_test SELECT generate_series(0,50000);
INSERT 0 50001

và xem cách nó phân phối các bản ghi đồng đều trong bảng con ...

severalnines_v11=# SELECT count(1),tableoid::regclass FROM part_hash_test GROUP by 2 order by 2 ;
 count |     tableoid
-------+------------------
 12537 | part_hash_test_0
 12473 | part_hash_test_1
 12509 | part_hash_test_2
 12482 | part_hash_test_3
(4 rows)

Chúng tôi không thể thay đổi số lượng phân vùng được chỉ định bởi `Modulus` trước đó, vì vậy bạn cần phải lập kế hoạch trước các yêu cầu về số lượng bảng phân vùng.

Nó sẽ xảy ra lỗi khi bạn cố gắng thêm một phân vùng mới với phần còn lại khác.

severalnines_v11=# CREATE TABLE part_hash_test_5 PARTITION OF part_hash_test FOR VALUES
WITH (MODULUS 4, REMAINDER 5);severalnines_v11-#
2018-11-21 01:51:28.966 IST [1675] ERROR:  remainder for hash partition must be less than modulus
2018-11-21 01:51:28.966 IST [1675] STATEMENT:  CREATE TABLE part_hash_test_5 PARTITION OF part_hash_test FOR VALUES  WITH (MODULUS 4, REMAINDER 5);

Phân vùng băm có thể hoạt động trên bất kỳ kiểu dữ liệu nào và nó cũng có thể hoạt động đối với kiểu UUID. Chúng tôi luôn khuyến nghị rằng số lượng bảng phải là lũy thừa của 2 và cũng không bắt buộc phải sử dụng cùng một mô-đun trong khi tạo bảng; điều này sẽ giúp tạo bảng phân vùng sau này theo yêu cầu.

Việc triển khai này cũng sẽ giúp chân không nhanh hơn và có thể cho phép tham gia phân vùng khôn ngoan.

Hỗ trợ khóa nước ngoài

Trước PostgreSQL 11, khóa ngoại trong bảng phân vùng không được hỗ trợ. Các khóa ngoại có thể có trong bảng phân vùng ngay bây giờ và dưới đây là cách ...

severalnines_v11=# CREATE TABLE customers2 ( cust_id integer PRIMARY KEY );
CREATE TABLE
severalnines_v11=# CREATE TABLE account (
    ac_date   date    NOT NULL,
    cust_id  integer REFERENCES customers2(cust_id),
     amount INTEGER NOT NULL) PARTITION BY RANGE (ac_date);
CREATE TABLE

Tạo chỉ mục tự động trên bảng con

Trong các phiên bản trước của PostgreSQL, việc tạo một chỉ mục trên mỗi bảng phân vùng là một nỗ lực thủ công. Trong PostgreSQL phiên bản 11, nó khá thuận tiện cho người dùng. Khi chỉ mục được tạo trên bảng chính, nó sẽ tự động tạo chỉ mục có cùng cấu hình trên tất cả các phân vùng con hiện có và quản lý cả các bảng phân vùng trong tương lai.

Chỉ mục được tạo trên Bảng chính

severalnines_v11=# CREATE index idx_name ON customers(cust_name);
CREATE INDEX

Nó tự động tạo chỉ mục trên tất cả các bảng con như bên dưới. (Xác minh bằng bảng danh mục)

severalnines_v11=# SELECT tablename,indexname,indexdef FROM pg_indexes WHERE tablename ilike '%customer_%';
   tablename   |          indexname          |       indexdef
---------------+-----------------------------+------------------------------------------------------------------------------------------
 customer_ind  | customer_ind_cust_name_idx  | CREATE INDEX customer_ind_cust_name_idx ON public.customer_ind USING btree (cust_name)
 customer_jap  | customer_jap_cust_name_idx  | CREATE INDEX customer_jap_cust_name_idx ON public.customer_jap USING btree (cust_name)
 customer_usa  | customer_usa_cust_name_idx  | CREATE INDEX customer_usa_cust_name_idx ON public.customer_usa USING btree (cust_name)
 customers_def | customers_def_cust_name_idx | CREATE INDEX customers_def_cust_name_idx ON public.customers_def USING btree (cust_name)
(4 rows)

Chỉ mục chỉ có thể được tạo trên bảng chính, không thể có trên bảng con. Không thể xóa từng chỉ mục được tạo tự động.

Tạo trình kích hoạt tự động trên bảng con

Khi trình kích hoạt được tạo trên bảng chính, nó sẽ tự động tạo trình kích hoạt trên tất cả các bảng con (hành vi này tương tự như hành vi được thấy đối với chỉ mục).

Có thể tạo chỉ mục duy nhất

Trong phiên bản 11, các chỉ mục duy nhất có thể được thêm vào bảng chính, điều này sẽ tạo ra ràng buộc duy nhất trên tất cả các bảng con hiện có và các bảng phân vùng trong tương lai.

Hãy tạo một bảng chính với các ràng buộc duy nhất.

CREATE TABLE uniq_customers(  cust_id bigint NOT NULL, cust_name varchar(32) NOT NULL, cust_address text, cust_country text,cust_email text, unique(cust_email,cust_id,cust_country)  )PARTITION BY LIST(cust_country);

Ràng buộc duy nhất đã được tạo tự động trên bảng con như bên dưới.

severalnines_v11=# SELECT table_name,constraint_name,constraint_type FROM information_schema.table_constraints WHERE table_name ilike '%uniq%' AND constraint_type = 'UNIQUE';
    table_name     |                    constraint_name                    | constraint_type
-------------------+-------------------------------------------------------+-----------------
 uniq_customers    | uniq_customers_cust_email_cust_id_cust_country_key    | UNIQUE
 uniq_customer_ind | uniq_customer_ind_cust_email_cust_id_cust_country_key | UNIQUE
(2 rows)

Thận trọng:Một ràng buộc duy nhất trên bảng mẹ không thực sự đảm bảo tính duy nhất trên toàn bộ hệ thống phân cấp phân vùng. Nó không phải là ràng buộc toàn cục, nó chỉ là cục bộ.

Tải xuống Báo cáo chính thức hôm nay Quản lý &Tự động hóa PostgreSQL với ClusterControlTìm hiểu về những điều bạn cần biết để triển khai, giám sát, quản lý và mở rộng PostgreSQLTải xuống Báo cáo chính thức

Hiệu suất truy vấn nhanh hơn

Cắt tỉa phân vùng động

Trong PostgreSQL 11, tìm kiếm nhị phân cho phép xác định nhanh hơn các bảng con được yêu cầu cho dù nó được phân vùng LIST hay RANGE. Hàm băm tìm phân vùng phù hợp cho phân vùng HASH. Nó thực sự tự động loại bỏ (các) bảng phân vùng không cần thiết và tăng hiệu suất Truy vấn.

Việc cắt tỉa phân vùng động có thể được kiểm soát bằng tham số `enable_partition_pruning`.

severalnines_v11=# show enable_partition_pruning;
 enable_partition_pruning
--------------------------
 off
(1 row)
severalnines_v11=# EXPLAIN SELECT * from customers where cust_country = 'ind';
                             QUERY PLAN
---------------------------------------------------------------------
 Append  (cost=0.00..18.54 rows=5 width=154)
   ->  Seq Scan on customer_ind  (cost=0.00..1.01 rows=1 width=154)
         Filter: (cust_country = 'ind'::text)
   ->  Seq Scan on customer_jap  (cost=0.00..1.00 rows=1 width=154)
         Filter: (cust_country = 'ind'::text)
   ->  Seq Scan on customer_usa  (cost=0.00..15.50 rows=2 width=154)
         Filter: (cust_country = 'ind'::text)
   ->  Seq Scan on customers_def  (cost=0.00..1.00 rows=1 width=154)
         Filter: (cust_country = 'ind'::text)
(9 rows)
Enabled the parameter to ON.
severalnines_v11=# set enable_partition_pruning TO on;
SET
severalnines_v11=# EXPLAIN SELECT * from customers where cust_country = 'ind';
                             QUERY PLAN
--------------------------------------------------------------------
 Append  (cost=0.00..1.02 rows=1 width=154)
   ->  Seq Scan on customer_ind  (cost=0.00..1.01 rows=1 width=154)
         Filter: (cust_country = 'ind'::text)
(3 rows)

Cách triển khai tuyệt vời khác giống như thế này.

Cắt tỉa phân vùng theo thời gian thực thi

Trong các phiên bản PostgreSQL trước 11, việc cắt bớt phân vùng chỉ có thể xảy ra tại thời điểm dự kiến; trình lập kế hoạch yêu cầu giá trị của khóa phân vùng để xác định phân vùng chính xác. Hành vi này được khắc phục trong PostgreSQL 11, vì bộ lập kế hoạch thời gian thực thi sẽ biết giá trị nào đang được cung cấp và dựa trên việc lựa chọn / loại bỏ phân vùng đó là có thể và sẽ chạy nhanh hơn rất nhiều. Trường hợp sử dụng có thể là một truy vấn sử dụng tham số (câu lệnh đã chuẩn bị) HOẶC truy vấn con cung cấp giá trị dưới dạng tham số.

Example : cus_country is partition key and getting value from subquery
severalnines_v11=# explain analyze  select * from customers WHERE cust_country = (select cust_count_x FROM test_execution_prun1);
                                                        QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
 Append  (cost=23.60..42.14 rows=5 width=154) (actual time=0.019..0.020 rows=0 loops=1)
   InitPlan 1 (returns $0)
     ->  Seq Scan on test_execution_prun1  (cost=0.00..23.60 rows=1360 width=32) (actual time=0.006..0.007 rows=1 loops=1)
   ->  Seq Scan on customer_ind  (cost=0.00..1.01 rows=1 width=154) (never executed)
         Filter: (cust_country = $0)
   ->  Seq Scan on customer_jap  (cost=0.00..1.00 rows=1 width=154) (never executed)
         Filter: (cust_country = $0)
   ->  Seq Scan on customer_usa  (cost=0.00..15.50 rows=2 width=154) (never executed)
         Filter: (cust_country = $0)
   ->  Seq Scan on customers_def  (cost=0.00..1.00 rows=1 width=154) (actual time=0.003..0.003 rows=0 loops=1)
         Filter: (cust_country = $0)
 Planning Time: 0.237 ms
 Execution Time: 0.057 ms
(13 rows)

Trong phần giải thích về kế hoạch ở trên, chúng ta có thể thấy, tại thời điểm thực thi, trình lập kế hoạch đang nhanh chóng xác định bảng phân vùng chính xác dựa trên giá trị tham số và chạy nhanh hơn nhiều và không tốn thời gian quét / lặp trên bảng phân vùng khác (xem không bao giờ phần thực hiện trong giải thích kế hoạch ở trên). Điều này rất mạnh mẽ và bắt đầu một kỷ nguyên mới về nâng cao hiệu suất trong phân vùng.

Tổng hợp thông minh phân vùng

Tham số:enable_partitionwise_aggregate

Nếu khóa phân vùng khớp với khóa phân nhóm, mọi phân vùng sẽ tạo ra một nhóm rời rạc thay vì quét tất cả phân vùng cùng một lúc. Nó sẽ thực hiện tổng hợp song song cho mỗi phân vùng và trong kết quả cuối cùng, nó sẽ kết hợp tất cả các kết quả.

severalnines_v11=# explain SELECT count(1),cust_country FROM customers GROUP BY 2;
                                 QUERY PLAN
----------------------------------------------------------------------------
 HashAggregate  (cost=21.84..23.84 rows=200 width=40)
   Group Key: customer_ind.cust_country
   ->  Append  (cost=0.00..19.62 rows=443 width=32)
         ->  Seq Scan on customer_ind  (cost=0.00..1.01 rows=1 width=32)
         ->  Seq Scan on customer_jap  (cost=0.00..1.00 rows=1 width=32)
         ->  Seq Scan on customer_usa  (cost=0.00..14.40 rows=440 width=32)
         ->  Seq Scan on customers_def  (cost=0.00..1.00 rows=1 width=32)
(7 rows)
severalnines_v11=# SET  enable_partitionwise_aggregate TO on;
SET
severalnines_v11=#  explain SELECT count(1),cust_country FROM customers GROUP BY 2;
                                 QUERY PLAN
----------------------------------------------------------------------------
 Append  (cost=1.01..22.67 rows=203 width=40)
   ->  HashAggregate  (cost=1.01..1.02 rows=1 width=40)
         Group Key: customer_ind.cust_country
         ->  Seq Scan on customer_ind  (cost=0.00..1.01 rows=1 width=32)
   ->  HashAggregate  (cost=1.00..1.01 rows=1 width=40)
         Group Key: customer_jap.cust_country
         ->  Seq Scan on customer_jap  (cost=0.00..1.00 rows=1 width=32)
   ->  HashAggregate  (cost=16.60..18.60 rows=200 width=40)
         Group Key: customer_usa.cust_country
         ->  Seq Scan on customer_usa  (cost=0.00..14.40 rows=440 width=32)
   ->  HashAggregate  (cost=1.00..1.01 rows=1 width=40)
         Group Key: customers_def.cust_country
         ->  Seq Scan on customers_def  (cost=0.00..1.00 rows=1 width=32)
(13 rows)

Điều này chắc chắn nhanh hơn vì nó bao gồm xử lý tổng hợp song song và quét trên mỗi phân vùng.

Truy vấn danh mục có thể được sử dụng để biết tất cả các bảng phân vùng mẹ.

SELECT relname FROM pg_class WHERE oid in (select partrelid FROM  pg_partitioned_table);

Ma trận tính năng phân vùng ngắn gọn

Tính năng phân vùng v11 v10
Phân vùng mặc định KHÔNG
Kế thừa bảng ngoại KHÔNG
Phân vùng bằng Hash Key KHÔNG
Hỗ trợ PK &FK KHÔNG
CẬP NHẬT khóa phân vùng KHÔNG
Các phụ lục tự động trên CT KHÔNG
Trình kích hoạt tự động trên CT KHÔNG
Cắt tỉa phân vùng thời gian thực thi KHÔNG
Phân vùng khôn ngoan Tham gia KHÔNG
prun phân vùng động KHÔNG

Tiếp theo là gì?

Hiệu suất phân vùng

Đây là một trong những lĩnh vực làm việc tích cực nhất hiện nay trong cộng đồng PostgreSQL. PostgreSQL Phiên bản 12 sẽ được đóng gói với nhiều cải tiến hiệu suất hơn nữa trong không gian phân vùng. Phiên bản 12 dự kiến ​​sẽ phát hành vào tháng 11 năm 2019.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. lỗi khi cài đặt psycopg2, không tìm thấy thư viện cho -lssl

  2. Thay đổi từ SQLite sang PostgreSQL trong một dự án Rails mới

  3. Cài đặt Postgis:loại hình học không tồn tại

  4. Truy vấn Postgres phức tạp

  5. Cài đặt Odoo trên Mac Không thể Thực thi Lệnh LESSC