मैं एक अद्यतन कर रहा हूँ जहाँ मुझे एक tstzrange
चर पर एक सटीक समानता की आवश्यकता होती है । ~ 1M पंक्तियों को संशोधित किया जाता है, और क्वेरी में ~ 13 मिनट लगते हैं। इसका परिणाम यहांEXPLAIN ANALYZE
देखा जा सकता है , और वास्तविक परिणाम क्वेरी प्लानर द्वारा अनुमानित अनुमानों से बेहद अलग हैं। समस्या यह है कि सूचकांक स्कैन t_range
एक पंक्ति को वापस करने की अपेक्षा करता है।
यह इस तथ्य से संबंधित प्रतीत होता है कि श्रेणी प्रकार के आंकड़े अन्य प्रकारों से भिन्न रूप से संग्रहीत किए जाते हैं। को देखते हुए pg_stats
स्तंभ के लिए देखने के लिए, n_distinct
है -1 और अन्य क्षेत्रों (जैसे most_common_vals
, most_common_freqs
) खाली हैं।
हालांकि, t_range
कहीं न कहीं आंकड़े जमा होने चाहिए । एक समान समान अद्यतन जहां मैं सटीक समानता के बजाय t_range पर 'भीतर' का उपयोग करता हूं, प्रदर्शन करने में लगभग 4 मिनट लगते हैं, और एक अलग तरह की क्वेरी योजना ( यहां देखें ) का उपयोग करता है । दूसरी क्वेरी योजना मुझे समझ में आती है क्योंकि अस्थायी तालिका में प्रत्येक पंक्ति और इतिहास तालिका का एक बड़ा अंश उपयोग किया जाएगा। इससे भी महत्वपूर्ण बात, क्वेरी प्लानर फिल्टर पर पंक्तियों की लगभग सही संख्या की भविष्यवाणी करता है t_range
।
का वितरण t_range
थोड़ा असामान्य है। मैं इस तालिका का उपयोग किसी अन्य तालिका की ऐतिहासिक स्थिति को संग्रहीत करने के लिए कर रहा हूं, और अन्य तालिका में परिवर्तन एक ही बार में बड़े डंप में होते हैं, इसलिए इसके कई अलग-अलग मूल्य नहीं हैं t_range
। यहाँ प्रत्येक अद्वितीय मानों की गणना की गई है t_range
:
t_range | count
-------------------------------------------------------------------+---------
["2014-06-12 20:58:21.447478+00","2014-06-27 07:00:00+00") | 994676
["2014-06-12 20:58:21.447478+00","2014-08-01 01:22:14.621887+00") | 36791
["2014-06-27 07:00:00+00","2014-08-01 07:00:01+00") | 1000403
["2014-06-27 07:00:00+00",infinity) | 36791
["2014-08-01 07:00:01+00",infinity) | 999753
t_range
ऊपर अलग-अलग के लिए गणना पूरी हो गई है, इसलिए कार्डिनैलिटी ~ 3M है (जिनमें से ~ 1M या तो अपडेट क्वेरी से प्रभावित होगा)।
क्वेरी 1 क्वेरी 2 की तुलना में बहुत अधिक खराब क्यों है? मेरे मामले में, क्वेरी 2 एक अच्छा विकल्प है, लेकिन अगर एक सटीक श्रेणी समानता वास्तव में आवश्यक थी, तो मैं एक स्मार्ट क्वेरी योजना का उपयोग करने के लिए पोस्टग्रैज को कैसे प्राप्त कर सकता हूं?
अनुक्रमित के साथ तालिका परिभाषा (अप्रासंगिक कॉलम छोड़ने):
Column | Type | Modifiers
---------------------+-----------+------------------------------------------------------------------------------
history_id | integer | not null default nextval('gtfs_stop_times_history_history_id_seq'::regclass)
t_range | tstzrange | not null
trip_id | text | not null
stop_sequence | integer | not null
shape_dist_traveled | real |
Indexes:
"gtfs_stop_times_history_pkey" PRIMARY KEY, btree (history_id)
"gtfs_stop_times_history_t_range" gist (t_range)
"gtfs_stop_times_history_trip_id" btree (trip_id)
क्वेरी 1:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND sth.t_range = '["2014-08-01 07:00:01+00",infinity)'::tstzrange;
क्वेरी 2:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND '2014-08-01 07:00:01+00'::timestamptz <@ sth.t_range;
Q1 अपडेट 999753 पंक्तियों और Q2 अद्यतनों 999753 + 36791 = 1036544 (यानी, अस्थायी तालिका ऐसी है कि समय सीमा की स्थिति को अद्यतन करने वाली प्रत्येक पंक्ति अद्यतन की जाती है)।
मैंने @ ypercube की टिप्पणी के जवाब में इस क्वेरी की कोशिश की :
क्वेरी 3:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND sth.t_range <@ '["2014-08-01 07:00:01+00",infinity)'::tstzrange
AND '["2014-08-01 07:00:01+00",infinity)'::tstzrange <@ sth.t_range;
क्वेरी योजना और परिणाम ( यहां देखें ) दो पिछले मामलों (~ 6 मिनट) के बीच मध्यवर्ती थे।
2016/02/05 EDIT
1.5 साल बाद डेटा तक पहुंच नहीं होने पर, मैंने एक ही संरचना (कोई अनुक्रमित के साथ) और समान कार्डिनैलिटी के साथ एक परीक्षण तालिका बनाई। jjanes के उत्तर ने प्रस्तावित किया कि इसका कारण अद्यतन के लिए उपयोग की गई अस्थायी तालिका का आदेश हो सकता है। मैं सीधे परिकल्पना का परीक्षण करने में असमर्थ था क्योंकि मेरे पास track_io_timing
(अमेज़ॅन आरडीएस का उपयोग) तक पहुंच नहीं है ।
समग्र परिणाम बहुत तेजी से (कई के एक कारक द्वारा) थे। मैं अनुमान लगा रहा हूं कि यह इरविन के जवाब के अनुरूप, सूचकांकों को हटाने के कारण है ।
इस परीक्षण के मामले में, क्वेरी 1 और 2 ने मूल रूप से समान समय लिया, क्योंकि वे दोनों मर्ज में शामिल हुए थे। यही है, हैश ज्वाइन को चुनने के लिए पोस्टग्रेज के कारण जो कुछ भी था, मैं उसे ट्रिगर करने में असमर्थ था, इसलिए मुझे इस पर कोई स्पष्टता नहीं है कि पोस्टग्रेज खराब प्रदर्शन करने वाले हैश को पहले स्थान पर क्यों चुन रहा है।
(lower(t_range),upper(t_range))
क्योंकि आप समानता की जांच करते हैं।
(a = b)
को दो "शर्तों" में बदल दिया है(a @> b AND b @> a)
:? क्या योजना बदलती है?