Làm mới chế độ xem được tăng dần trong PostgreSQL


33

Có thể làm mới một khung nhìn cụ thể hóa tăng dần trong PostgreSQL tức là chỉ đối với dữ liệu mới hoặc đã thay đổi?

Xem xét bảng này và xem cụ thể hóa:

CREATE TABLE graph (
   xaxis integer NOT NULL,
   value integer NOT NULL,
);

CREATE MATERIALIZED VIEW graph_avg AS 
SELECT xaxis, AVG(value)
FROM graph
GROUP BY xaxis

Định kỳ, các giá trị mới được thêm vào graphhoặc một giá trị hiện có được cập nhật. Tôi muốn làm mới chế độ xem graph_avgmỗi vài giờ chỉ với các giá trị đã được cập nhật. Tuy nhiên, trong PostgreSQL 9.3, toàn bộ bảng được làm mới. Điều này khá tốn thời gian. Phiên bản tiếp theo 9.4 cho phép CONCURRENTcập nhật nhưng nó vẫn làm mới toàn bộ khung nhìn. Với hàng trăm triệu hàng, việc này mất vài phút.

Cách tốt để theo dõi các giá trị mới và cập nhật và chỉ làm mới chế độ xem một phần?

Câu trả lời:


22

Bạn luôn có thể triển khai bảng của riêng mình dưới dạng "khung nhìn cụ thể". Đó là những gì bạn phải làm trước đây MATERIALIZED VIEWđược thực hiện trong Postgres 9.3.

Chẳng hạn, bạn có thể tạo một đồng bằng VIEW:

CREATE VIEW graph_avg_view AS 
SELECT xaxis, AVG(value) AS avg_val
FROM   graph
GROUP  BY xaxis;

Và cụ thể hóa kết quả một lần hoặc bất cứ khi nào bạn cần bắt đầu lại:

CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view

(Hoặc sử dụng SELECTcâu lệnh trực tiếp mà không cần tạo VIEW.)
Sau đó, tùy thuộc vào chi tiết không được tiết lộ về trường hợp sử dụng của bạn, bạn có thể DELETE/ UPDATE/ INSERTthay đổi theo cách thủ công.

Một câu lệnh DML cơ bản với các CTE sửa đổi dữ liệu cho bảng của bạn như sau:

Giả sử không ai cố gắng khác để ghi tới graph_avgđồng thời (đọc là không có vấn đề):

WITH del AS (
   DELETE FROM graph_avg t
   WHERE  NOT EXISTS (SELECT 1 FROM graph_avg_view v WHERE v.xaxis = v.xaxis);
   )
, upd AS (
   UPDATE graph_avg t
   FROM   graph_avg_view v
   WHERE  t.xaxis = v.xaxis
   AND    t.avg_val <> v.avg_val
   )
INSERT INTO graph_avg t
SELECT *
FROM   graph_avg_view v
LEFT   JOIN graph_avg t USING (xaxis)
WHERE  t.xaxis IS NULL;

Nhưng điều này có lẽ nên được tối ưu hóa.

Công thức cơ bản:

  • Thêm một timestampcột với mặc định now()vào bảng cơ sở của bạn. Hãy gọi nó là ts.
    • Nếu bạn có các bản cập nhật, hãy thêm một kích hoạt để đặt dấu thời gian hiện tại với mỗi bản cập nhật thay đổi xaxishoặc value.
  • Tạo một bảng nhỏ để ghi nhớ dấu thời gian của ảnh chụp mới nhất của bạn. Hãy gọi nó là mv:

    CREATE TABLE mv (
       tbl text PRIMARY KEY
     , ts timestamp NOT NULL DEFAULT '-infinity'
    ); -- possibly more details
  • Tạo chỉ mục một phần, nhiều màu này:

    CREATE INDEX graph_mv_latest ON graph (xaxis, value)
    WHERE  ts >= '-infinity';
  • Sử dụng dấu thời gian của ảnh chụp nhanh cuối cùng làm vị ngữ trong các truy vấn của bạn để làm mới ảnh chụp nhanh với việc sử dụng chỉ mục hoàn hảo.

  • Khi kết thúc giao dịch, bỏ chỉ mục và tạo lại nó bằng dấu thời gian giao dịch thay thế dấu thời gian trong vị từ chỉ mục (ban đầu '-infinity'), mà bạn cũng lưu vào bảng của mình. Tất cả mọi thứ trong một giao dịch.

  • Lưu ý rằng chỉ mục một phần là tuyệt vời để bao gồm INSERTUPDATEhoạt động, nhưng không DELETE. Để bao quát điều đó, bạn cần xem xét toàn bộ bảng. Tất cả phụ thuộc vào yêu cầu chính xác.


Cảm ơn bạn đã rõ ràng về quan điểm cụ thể hóa và đề xuất một câu trả lời thay thế.
dùng4150760

13

Cập nhật đồng thời (Postgres 9.4)

Mặc dù không phải là bản cập nhật gia tăng như bạn yêu cầu, Postgres 9.4 cung cấp tính năng cập nhật đồng thời mới .

Để trích dẫn tài liệu

Trước PostgreQuery 9.4, làm mới một khung nhìn cụ thể hóa có nghĩa là khóa toàn bộ bảng và do đó ngăn chặn mọi thứ truy vấn nó và nếu làm mới mất một thời gian dài để có được khóa độc quyền (trong khi nó chờ các truy vấn sử dụng nó để kết thúc), thì đến lượt nó đang giữ các truy vấn tiếp theo. Điều này hiện có thể được giảm nhẹ bằng từ khóa CONCURRENTLY:

 postgres=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_data;

Một chỉ mục duy nhất sẽ cần tồn tại trên quan điểm cụ thể hóa. Thay vì khóa chế độ xem được vật chất hóa, thay vào đó, nó tạo ra một phiên bản cập nhật tạm thời của nó, so sánh hai phiên bản, sau đó áp dụng CHỨNG CHỈ và XÓA đối với chế độ xem cụ thể hóa để áp dụng sự khác biệt. Điều này có nghĩa là các truy vấn vẫn có thể sử dụng chế độ xem cụ thể hóa trong khi nó được cập nhật. Không giống như hình thức không đồng thời của nó, các bộ dữ liệu không bị đóng băng và nó cần VACUUMing do các XÓA đã nói ở trên sẽ để lại các bộ dữ liệu chết.

Bản cập nhật đồng thời này vẫn đang thực hiện một truy vấn mới hoàn chỉnh (không tăng dần). Vì vậy, CONCURRENTLY không tiết kiệm thời gian tính toán tổng thể, nó chỉ giảm thiểu lượng thời gian mà chế độ xem cụ thể hóa của bạn không có sẵn để sử dụng trong quá trình cập nhật.


11
Trong một khoảnh khắc tôi đã phấn khích cho đến khi tôi đọc kỹ. it instead creates a temporary updated version of it...compares the two versions- Điều này có nghĩa là phiên bản cập nhật tạm thời vẫn là một tính toán đầy đủ, sau đó nó áp dụng sự khác biệt cho chế độ xem hiện tại. Vì vậy, về cơ bản, tôi vẫn đang làm lại TẤT CẢ các tính toán, nhưng chỉ trong bảng tạm thời.
dùng4150760

5
À, đúng rồi CONCURRENTLY không tiết kiệm thời gian tính toán tổng thể, nó chỉ giảm thiểu lượng thời gian mà chế độ xem cụ thể của bạn không có sẵn để sử dụng trong quá trình cập nhật.
Basil Bourque
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.