आपको now()
. का उपयोग करके एक अपवाद मिलता है क्योंकि फ़ंक्शन IMMUTABLE
नहीं है (जाहिर है) और, मैनुअल को उद्धृत करते हुए
:
मुझे एक (अधिक कुशल) आंशिक अनुक्रमणिका का उपयोग करने के दो तरीके दिखाई देते हैं:
<एच4>1. स्थिर . का उपयोग करके शर्त के साथ आंशिक अनुक्रमणिका दिनांक:CREATE INDEX queries_recent_idx ON queries_query (user_sid, created)
WHERE created > '2013-01-07 00:00'::timestamp;
मानते हैं created
वास्तव में timestamp
. के रूप में परिभाषित किया गया है . यह timestamp
प्रदान करने के लिए काम नहीं करेगा timestamptz
. के लिए स्थिरांक कॉलम (timestamp with time zone
) timestamp
. से कास्ट करने के लिए timestamptz
(या इसके विपरीत) वर्तमान समय क्षेत्र सेटिंग पर निर्भर करता है और अपरिवर्तनीय नहीं . है . मिलान डेटा प्रकार के स्थिरांक का उपयोग करें। टाइम ज़ोन के साथ/बिना टाइमस्टैम्प की मूल बातें समझें:
छोड़ें और फिर से बनाएं कम ट्रैफ़िक वाले घंटों में वह इंडेक्स, शायद दैनिक या साप्ताहिक आधार पर क्रॉन जॉब के साथ (या जो कुछ भी आपके लिए पर्याप्त हो)। एक सूचकांक बनाना बहुत तेज़ है, विशेष रूप से एक आंशिक सूचकांक जो तुलनात्मक रूप से छोटा है। इस समाधान को तालिका में कुछ भी जोड़ने की आवश्यकता नहीं है।
मान लें कि समवर्ती पहुंच नहीं है तालिका में, स्वचालित अनुक्रमणिका मनोरंजन इस तरह के एक समारोह के साथ किया जा सकता है:
CREATE OR REPLACE FUNCTION f_index_recreate()
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
DROP INDEX IF EXISTS queries_recent_idx;
EXECUTE format('
CREATE INDEX queries_recent_idx
ON queries_query (user_sid, created)
WHERE created > %L::timestamp'
, LOCALTIMESTAMP - interval '30 days'); -- timestamp constant
-- , now() - interval '30 days'); -- alternative for timestamptz
END
$func$;
कॉल करें:
SELECT f_index_recreate();
now()
(जैसा आपने किया था) CURRENT_TIMESTAMP
. के बराबर है और देता है timestamptz
. timestamp
. पर कास्ट करें now()::timestamp
. के साथ या LOCALTIMESTAMP
. का उपयोग करें इसके बजाय।
db<>fiddle यहां
पुराना sqlfiddle
उप>
अगर आपको समवर्ती पहुंच . से निपटना है तालिका में, DROP INDEX CONCURRENTLY
और CREATE INDEX CONCURRENTLY
. लेकिन आप इन आदेशों को एक फ़ंक्शन में लपेट नहीं सकते क्योंकि, प्रति दस्तावेज़
:
तो, दो अलग-अलग लेन-देन . के साथ :
CREATE INDEX CONCURRENTLY queries_recent_idx2 ON queries_query (user_sid, created)
WHERE created > '2013-01-07 00:00'::timestamp; -- your new condition
फिर:
DROP INDEX CONCURRENTLY IF EXISTS queries_recent_idx;
वैकल्पिक रूप से, पुराने नाम का नाम बदलें:
ALTER INDEX queries_recent_idx2 RENAME TO queries_recent_idx;
<एच4>2. "संग्रहीत" टैग पर शर्त के साथ आंशिक अनुक्रमणिका
एक archived
जोड़ें अपनी तालिका में टैग करें:
ALTER queries_query ADD COLUMN archived boolean NOT NULL DEFAULT FALSE;
UPDATE
पुरानी पंक्तियों को "रिटायर" करने और एक इंडेक्स बनाने के लिए अपने चयन के अंतराल पर कॉलम:
CREATE INDEX some_index_name ON queries_query (user_sid, created)
WHERE NOT archived;
अनुक्रमणिका का उपयोग करने की अनुमति देने के लिए अपने प्रश्नों में एक मिलान शर्त जोड़ें (भले ही यह बेमानी लगे)। EXPLAIN ANALYZE
के साथ जांचें क्या क्वेरी प्लानर पकड़ में आता है - यह नई तारीख पर प्रश्नों के लिए इंडेक्स का उपयोग करने में सक्षम होना चाहिए। लेकिन यह अधिक जटिल स्थितियों को नहीं समझेगा जो सटीक रूप से मेल नहीं खा रही हैं।
आपको इंडेक्स को छोड़ने और फिर से बनाने की ज़रूरत नहीं है, लेकिन UPDATE
तालिका पर अनुक्रमणिका मनोरंजन की तुलना में अधिक महंगा हो सकता है और तालिका थोड़ी बड़ी हो जाती है।
मैं पहले . के साथ जाऊंगा विकल्प (सूचकांक मनोरंजन)। वास्तव में, मैं इस समाधान का उपयोग कई डेटाबेस में कर रहा हूं। दूसरा अधिक महंगा अपडेट लेता है।
दोनों समाधान समय के साथ अपनी उपयोगिता बनाए रखते हैं, प्रदर्शन धीरे-धीरे बिगड़ता है क्योंकि अधिक पुरानी पंक्तियों को अनुक्रमणिका में शामिल किया जाता है।