รีเฟรชมุมมอง materalized ที่เพิ่มขึ้นใน PostgreSQL


33

เป็นไปได้ไหมที่จะรีเฟรชมุมมองที่เป็นรูปธรรมเพิ่มขึ้นใน PostgreSQL เช่นสำหรับข้อมูลที่ใหม่หรือมีการเปลี่ยนแปลงเท่านั้น

พิจารณาตารางนี้และมุมมองที่ปรากฏขึ้น:

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

มีการเพิ่มค่าใหม่เป็นระยะgraphหรือปรับปรุงค่าที่มีอยู่เป็นระยะ ฉันต้องการรีเฟรชมุมมองgraph_avgทุกสองสามชั่วโมงเฉพาะค่าที่อัปเดต อย่างไรก็ตามใน PostgreSQL 9.3 ตารางทั้งหมดจะถูกรีเฟรช ใช้เวลาค่อนข้างนาน เวอร์ชันถัดไป 9.4 อนุญาตให้CONCURRENTอัพเดต แต่ยังคงรีเฟรชมุมมองทั้งหมด ด้วยจำนวนแถว 100 ล้านแถวซึ่งใช้เวลาไม่กี่นาที

เป็นวิธีที่ดีในการติดตามการปรับปรุงและค่าใหม่และฟื้นฟูมุมมองเพียงบางส่วนเท่านั้น?

คำตอบ:


22

คุณสามารถใช้การแสดงตารางของคุณเองเป็น "มุมมองที่ปรากฏขึ้น" ได้เสมอ นั่นคือสิ่งที่คุณต้องทำก่อนMATERIALIZED VIEWนำไปใช้ใน Postgres 9.3 ไม่ว่าจะด้วยวิธีใด

ตัวอย่างเช่นคุณสามารถสร้างธรรมดาVIEW:

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

และแสดงผลลัพธ์โดยรวมเพียงครั้งเดียวหรือเมื่อใดก็ตามที่คุณต้องการเริ่มต้นใหม่:

CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view

(หรือใช้SELECTคำสั่งโดยตรงโดยไม่ต้องสร้าง a VIEW.)
จากนั้นขึ้นอยู่กับรายละเอียดที่ไม่เปิดเผยของกรณีการใช้งานของคุณคุณสามารถDELETE/ UPDATE/ INSERTเปลี่ยนแปลงด้วยตนเอง

คำสั่ง DML พื้นฐานพร้อม CTE ที่แก้ไขข้อมูลสำหรับตารางของคุณตามที่เป็น :

สมมติว่าไม่มีใครพยายามเขียนไปgraph_avgพร้อม ๆ กัน (การอ่านไม่มีปัญหา):

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;

แต่สิ่งนี้น่าจะเหมาะสมที่สุด

สูตรพื้นฐาน:

  • เพิ่มtimestampคอลัมน์ที่มีค่าเริ่มต้นnow()ลงในตารางฐานของคุณ tsขอเรียกว่า
    • หากคุณมีการปรับปรุงเพิ่มการเรียกการตั้งค่าการประทับเวลาในปัจจุบันมีการปรับปรุงที่เปลี่ยนแปลงทุกอย่างใดอย่างหนึ่งหรือxaxisvalue
  • สร้างตารางเล็ก ๆ เพื่อจดจำการประทับเวลาของสแน็ปช็อตล่าสุดของคุณ เรียกมันว่าmv:

    CREATE TABLE mv (
       tbl text PRIMARY KEY
     , ts timestamp NOT NULL DEFAULT '-infinity'
    ); -- possibly more details
  • สร้างดัชนีหลายส่วนบางส่วนนี้:

    CREATE INDEX graph_mv_latest ON graph (xaxis, value)
    WHERE  ts >= '-infinity';
  • ใช้การประทับเวลาของสแน็ปช็อตสุดท้ายเป็นเพรดิเคตในแบบสอบถามของคุณเพื่อรีเฟรชสแน็ปช็อตด้วยการใช้ดัชนีที่สมบูรณ์แบบ

  • ในตอนท้ายของการทำธุรกรรมให้วางดัชนีและสร้างใหม่ด้วยการประทับเวลาของธุรกรรมแทนที่การประทับเวลาในภาคแสดงดัชนี (เริ่มแรก '-infinity') ซึ่งคุณจะบันทึกลงในตารางของคุณด้วย ทุกอย่างในหนึ่งธุรกรรม

  • หมายเหตุว่าดัชนีบางส่วนเป็นที่ดีที่ปกINSERTและUPDATEการดำเนินงาน DELETEแต่ไม่ได้ เพื่อให้ครอบคลุมนั้นคุณจะต้องพิจารณาทั้งตาราง ทุกอย่างขึ้นอยู่กับข้อกำหนดที่แน่นอน


ขอบคุณสำหรับความชัดเจนในมุมมองที่เกิดขึ้นจริงและแนะนำคำตอบอื่น
user4150760

13

การอัพเดทพร้อมกัน (Postgres 9.4)

แม้ว่าจะไม่ใช่การอัปเดตที่เพิ่มขึ้นตามที่คุณถาม แต่ Postgres 9.4 จะมีคุณสมบัติการอัพเดทพร้อมกันใหม่

เพื่ออ้างถึงเอกสาร ...

ก่อนที่จะ PostgreSQL 9.4 การรีเฟรชมุมมอง materialized หมายถึงการล็อกทั้งตารางและดังนั้นจึงป้องกันสิ่งใดก็ตามที่ทำการสืบค้นและหากการรีเฟรชใช้เวลานานในการรับการล็อคแบบเอกสิทธิ์เฉพาะบุคคล กำลังถือคิวรีที่ตามมา สิ่งนี้สามารถลดลงได้ด้วยคำหลักอย่างต่อเนื่อง:

 postgres=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_data;

ดัชนีที่ไม่ซ้ำกันจะต้องมีอยู่ในมุมมองที่ปรากฏขึ้น แทนที่จะล็อคมุมมอง materialized ขึ้นแทนที่จะสร้างเวอร์ชันที่อัพเดตชั่วคราวเปรียบเทียบสองเวอร์ชันจากนั้นใช้ INSERTs และ DELETE กับมุมมอง materialized เพื่อใช้ความแตกต่าง ซึ่งหมายความว่าแบบสอบถามยังคงสามารถใช้มุมมองที่ปรากฏขึ้นในขณะที่กำลังอัปเดต ซึ่งแตกต่างจากรูปแบบที่ไม่เกิดขึ้นพร้อมกัน tuples จะไม่ถูกแช่แข็งและต้องการ VACUUMing เนื่องจากการลบดังกล่าวข้างต้นที่จะทำให้สิ่งอันดับที่ตายแล้วอยู่ด้านหลัง

การปรับปรุงพร้อมกันนี้ยังคงดำเนินการแบบสอบถามใหม่ที่สมบูรณ์ (ไม่เพิ่ม) ดังนั้นจะไม่ประหยัดในเวลาการคำนวณโดยรวมเพียงแค่ลดระยะเวลาที่คุณใช้ในการดูระหว่างการอัพเดต


11
ครู่หนึ่งฉันตื่นเต้นจนฉันอ่านอย่างใกล้ชิด it instead creates a temporary updated version of it...compares the two versions- ซึ่งหมายความว่าเวอร์ชันที่อัปเดตชั่วคราวนั้นยังคงเป็นการคำนวณเต็มรูปแบบจากนั้นจะใช้ความแตกต่างกับมุมมองที่มีอยู่ โดยพื้นฐานแล้วฉันยังคงทำการคำนวณทั้งหมดอีกครั้ง แต่อยู่ในตารางชั่วคราว
user4150760

5
อ๊ะจริงCONCURRENTLYไม่ได้ประหยัดเวลาการคำนวณโดยรวมเพียงแค่ลดระยะเวลาที่คุณจะไม่สามารถใช้มุมมองที่เป็นรูปธรรมในระหว่างการอัปเดตได้
Basil Bourque
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.