Tối ưu hóa cập nhật đồng thời trong Postgres


9

Tôi đang chạy các truy vấn Postgres đồng thời như thế này:

UPDATE foo SET bar = bar + 1 WHERE baz = 1234

Mỗi truy vấn ảnh hưởng đến số lượng hàng K cố định và tôi không thể tìm ra cách thực thi thứ tự các hàng được cập nhật, tôi kết thúc bằng các khóa chết. Hiện tại tôi đã khắc phục sự cố bằng cách thực thi lệnh bằng tay, nhưng điều này có nghĩa là tôi phải thực thi nhiều truy vấn hơn bình thường trong khi cũng tăng độ phức tạp tìm kiếm từ O (log N + K) lên O (K log N).

Có cách nào để cải thiện hiệu suất mà không kết thúc dễ bị bế tắc? Tôi nghi ngờ rằng việc thay thế (baz)chỉ mục bằng (baz, id)chỉ mục có thể hoạt động với điều kiện Postgres cập nhật các hàng theo cùng thứ tự mà nó đã quét chúng, đây có phải là một cách tiếp cận đáng để theo đuổi không?


Tôi đề nghị bạn thêm CREATE TABLEmã.
ypercubeᵀᴹ

Câu trả lời:


15

Không có ORDER BYtrong một SQL UPDATElệnh. Postgres cập nhật các hàng theo thứ tự tùy ý:

Để tránh bế tắc với sự chắc chắn tuyệt đối, bạn có thể chạy các câu lệnh của mình trong sự cô lập giao dịch tuần tự . Nhưng điều đó đắt hơn và bạn cần chuẩn bị để lặp lại các lệnh về lỗi tuần tự hóa.

Hành động tốt nhất của bạn có lẽ là khóa rõ ràng với SELECT ... ORDER BY ... FOR UPDATEmột truy vấn con hoặc độc lập SELECTtrong một giao dịch - mặc định là mức độ cô lập "đọc cam kết". Trích dẫn Tom Lane trên pssql-general :

Sẽ ổn thôi --- khóa FOR UPDATE luôn là bước cuối cùng trong đường dẫn CHỌN.

Điều này sẽ làm công việc:

BEGIN;

SELECT 1
FROM   foo 
WHERE  baz = 1234
ORDER  BY bar
FOR    UPDATE;

UPDATE foo
SET    bar = bar + 1
WHERE  baz = 1234;

COMMIT;

Một chỉ số nhiều màu trên (baz, bar)có thể là hoàn hảo cho hiệu suất. Nhưng vì barrõ ràng là được cập nhật rất nhiều , chỉ mục một cột trên (baz)có thể thậm chí còn tốt hơn. Phụ thuộc vào một vài yếu tố. Có bao nhiêu hàng mỗi baz? Có thể cập nhật HOT mà không có chỉ số nhiều màu? ...

Nếu baz được cập nhật đồng thời, vẫn có khả năng xảy ra trường hợp góc đối với các xung đột (theo tài liệu) :

Có thể một SELECTlệnh chạy ở READ COMMITTED mức cô lập giao dịch và sử dụng ORDER BYvà một mệnh đề khóa để trả về các hàng không theo thứ tự. ...

Ngoài ra, nếu bạn nên có một ràng buộc duy nhất liên quan bar, hãy xem xét một DEFERRABLEràng buộc để tránh các vi phạm duy nhất trong cùng một lệnh. Câu trả lời liên quan:


1
NẾU tôi đang đặt hàng theo idhoặc một số cột duy nhất khác thay vì bar, không nên có một trường hợp góc hoặc một hiệu suất hit, phải không?
Alexei Averunn

@AlexeiAverchenko: Có, một cột duy nhất không bao giờ được cập nhật sẽ là hoàn hảo cho điều này - và một chỉ số nhiều màu bao gồm cột này ở vị trí thứ hai.
Erwin Brandstetter
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.