PostgreSQL Upsert không hoạt động trên Bảng được phân vùng


9

Có một bảng như thế này:

CREATE TABLE aggregated_master (
  "user"       BIGINT,
  type         TEXT,
  date         TIMESTAMP,
  operations   BIGINT,
  amount       NUMERIC,
  PRIMARY KEY ( "user", type, date )
);

Bảng này là chủ từ đó rất nhiều phân vùng kế thừa. Các phân vùng được thực hiện bởi MONTH trong trường DATE. Ví dụ: Phân vùng cho tháng 8 năm 2017 sẽ là agg_201708 và PK của nó sẽ là pk_agg_201708 Có một trình kích hoạt thông thường TRƯỚC KHI CHỌN để chuyển hướng chèn vào phân vùng thích hợp.

Có điều là tôi muốn thực hiện một UPSERT vào bảng này. Phần DO CONFLICT không hoạt động.

Mã đầu tiên là như thế này

INSERT INTO aggregated_master (user, type, date, oeprations, amount)
SELECT user, type, date, SUM(ops), SUM(amt)
FROM ...
WHERE ...
GROUP BY USER, TYPE, DATE
ON CONFLICT ON CONSTRAINT pk_aggregated
DO UPDATE SET operations = EXCLUDED.operations
          ,   amount = EXCLUDED.amount

Nhưng sau đó tôi nhận thấy rằng ràng buộc (pk_aggregated) là ràng buộc trên bảng chính, chứ không phải trên bảng con nơi chèn sẽ thực sự được thực hiện, do kích hoạt.

Tôi đã thay đổi mệnh đề CONFLICT thành:

ON CONFLICT (user, type, date)

Đó là các lĩnh vực của PK, nhưng điều này cũng không hoạt động.

Bất kỳ ý tưởng làm thế nào để làm cho công việc này?


2
Đừng nghĩ rằng nó sẽ do những hạn chế trong việc thực hiện. Nó thực sự nên phát hiện ra điều đó và LRI. Báo cáo lỗi?
Craig Ringer

5
Xem thêm danh sách gửi thư này chủ đề postgresql.org/message-id/ từ
Craig Ringer

Câu trả lời:


6

PostgreSQL 11 hỗ trợ INSERT INTO ... ON CONFLICTvới các bảng được phân đoạn:

CREATE TABLE o(id INT PRIMARY KEY, i INT) PARTITION BY RANGE (id);

CREATE TABLE o1 PARTITION OF o FOR VALUES FROM (1) TO (1000);
CREATE TABLE o2 PARTITION OF o FOR VALUES FROM (1000) TO (2000);

INSERT INTO o(id, i) VALUES (1,1),(2,2),(1500,1500);

INSERT INTO o(id, i)
VALUES (1500, 1400), (2,20), (3, 3)
ON CONFLICT (id)
DO UPDATE SET i = EXCLUDED.i;

SELECT * FROM o;

Trình diễn DBFiddle


Giới hạn phân vùng ddl

5.10.2.3. Hạn chế

Sử dụng mệnh đề ON CONFLICT với các bảng được phân đoạn sẽ gây ra lỗi, bởi vì các ràng buộc loại trừ hoặc duy nhất chỉ có thể được tạo trên các phân vùng riêng lẻ. Không có hỗ trợ để thực thi tính duy nhất (hoặc ràng buộc loại trừ) trên toàn bộ phân cấp phân vùng.

đã được dỡ bỏ.


11

Upsert trên các bảng được phân đoạn không được triển khai trong các phiên bản sớm hơn Postgres 11.

Trong Postgres 9.6:

Các câu lệnh INSERT với các mệnh đề ON CONFLICT dường như không hoạt động như mong đợi, vì hành động ON CONFLICT chỉ được thực hiện trong trường hợp vi phạm duy nhất đối với quan hệ mục tiêu đã chỉ định, chứ không phải quan hệ con của nó.

Phân vùng khai báo không giải quyết được vấn đề, Postgres 10:

Sử dụng mệnh đề ON CONFLICT với các bảng được phân đoạn sẽ gây ra lỗi, bởi vì các ràng buộc loại trừ hoặc duy nhất chỉ có thể được tạo trên các phân vùng riêng lẻ. Không có hỗ trợ để thực thi tính duy nhất (hoặc ràng buộc loại trừ) trên toàn bộ phân cấp phân vùng.

Giải pháp thay thế

Trong Postgres 11, bạn có thể sử dụng ON CONFLICTtrên các bảng được phân đoạn, xem câu trả lời của lad2025.


Câu trả lời này cần được cập nhật cho pg11, thực hiện nó, như ghi chú @ lad2025.
DB140141

@ DB140141 - thx, câu trả lời được cập nhật.
klin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.