PostgreSQL में वृद्धिशील दृश्य को ताज़ा करें


33

क्या पोस्टग्रेक्यूएल में एक भौतिक दृष्टि से वृद्धि को ताज़ा करना संभव है यानी केवल उस डेटा के लिए जो नया है या बदल गया है?

इस तालिका और भौतिक दृष्टिकोण पर विचार करें:

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पोस्टग्रेज 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स्टेटमेंट का उपयोग सीधे करें, बिना क्रिएट किए VIEW।)
फिर, आपके उपयोग के मामले के अज्ञात विवरण के आधार पर, आप मैन्युअल रूप से DELETE/ UPDATE/ INSERTबदल सकते हैं ।

आपकी तालिका के लिए डेटा-संशोधित CTE के साथ एक बुनियादी DML कथन है :

करने के लिए किसी और की कोशिश करता मान लिया जाये कि लिखने के लिए 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
    • यदि आपके पास अपडेट हैं, तो वर्तमान टाइमस्टैम्प को हर अपडेट के साथ सेट करने के लिए एक ट्रिगर जोड़ें जो xaxisया तो बदलता है value
  • अपने नवीनतम स्नैपशॉट के टाइमस्टैम्प को याद करने के लिए एक छोटी सी तालिका बनाएँ। चलो इसे कॉल करें 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

समवर्ती अद्यतन (पोस्टग्रैड 9.4)

जबकि एक वृद्धिशील अद्यतन नहीं जैसा कि आपने पूछा था, Postgres 9.4 एक नया समवर्ती अद्यतन सुविधा प्रदान करता है ।

डॉक्टर को उद्धृत करने के लिए ...

PostgreSQL 9.4 से पहले, एक भौतिक दृष्टिकोण को ताज़ा करने का मतलब था कि पूरी मेज को लॉक करना, और इसलिए इसे क्वेरी करने से कुछ भी रोकना, और यदि किसी ताज़ा को एक्सक्लूसिव लॉक हासिल करने में लंबा समय लगा (जबकि इसे समाप्त करने के लिए प्रश्नों का इंतजार है), तो यह बदले में है बाद के प्रश्नों को पकड़ रहा है। इसे अब CONCURRENTLY कीवर्ड के साथ कम किया जा सकता है:

 postgres=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_data;

एक अनोखे इंडेक्स को हालांकि भौतिकवादी दृष्टिकोण पर मौजूद होना चाहिए। भौतिकीकृत दृश्य को लॉक करने के बजाय, यह इसके बजाय एक अस्थायी अद्यतन संस्करण बनाता है, दो संस्करणों की तुलना करता है, फिर अंतर को लागू करने के लिए भौतिक दृश्य के खिलाफ INSERT और DELETE लागू करता है। इसका मतलब यह है कि क्वेरीज़ अभी भी अपडेट किए जाने के दौरान भौतिकतावादी दृष्टिकोण का उपयोग कर सकते हैं। इसके गैर-समवर्ती रूप के विपरीत, ट्यूपल्स जमे हुए नहीं हैं, और इसे उपरोक्त DELETE के कारण रिक्त स्थान की आवश्यकता है जो मृत ट्यूपल्स को पीछे छोड़ देगा।

यह समवर्ती अद्यतन अभी भी एक पूर्ण ताज़ा क्वेरी (वृद्धिशील नहीं) कर रहा है। इसलिए समग्र रूप से गणना समय पर बचत नहीं करता है, यह सिर्फ आपके भौतिक दृश्य को अपडेट के दौरान उपयोग के लिए अनुपलब्ध समय की मात्रा को कम करता है।


11
एक पल के लिए मैं उत्साहित था जब तक मैं बारीकी से नहीं पढ़ा। it instead creates a temporary updated version of it...compares the two versions- इसका मतलब है कि अस्थायी अपडेटेड संस्करण अभी भी एक पूर्ण संगणना है, फिर यह मौजूदा दृश्य के अंतर को लागू करता है। इसलिए अनिवार्य रूप से, मैं अभी भी सभी गणना कर रहा हूं, लेकिन सिर्फ अस्थायी तालिका में।
user4150760

5
आह, सच, CONCURRENTLYसमग्र संगणना समय पर नहीं बचाता है, यह सिर्फ आपके भौतिक दृश्य को अपडेट के दौरान उपयोग के लिए अनुपलब्ध समय की मात्रा को कम करता है।
तुलसी बॉर्क
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.