पोस्टग्रे में छँटाई करने के लिए सूचकांक का उपयोग कैसे करें


10

मैं postgres 9.4 का उपयोग कर रहा हूं।

messagesनिम्न स्कीमा है: संदेशों FEED_ID के अंतर्गत आता है, और posted_at है, यह भी एक माता पिता संदेशों संदेश (उत्तर के मामले में) हो सकता है।

                    Table "public.messages"
            Column            |            Type             | Modifiers
------------------------------+-----------------------------+-----------
 message_id                   | character varying(255)      | not null
 feed_id                      | integer                     |
 parent_id                    | character varying(255)      |
 posted_at                    | timestamp without time zone |
 share_count                  | integer                     |
Indexes:
    "messages_pkey" PRIMARY KEY, btree (message_id)
    "index_messages_on_feed_id_posted_at" btree (feed_id, posted_at DESC NULLS LAST)

मैं आदेश दिए गए सभी संदेशों को वापस करना चाहता हूं share_count, लेकिन प्रत्येक के लिए parent_id, मैं केवल एक संदेश वापस करना चाहता हूं। यानी, यदि कई संदेशों में समान है parent_id, तो केवल नवीनतम एक ( posted_at) लौटाया जाता है। parent_idअशक्त हो सकता है, शून्य वाले संदेशों parent_idसब वापस आ जाएगी।

मेरे द्वारा उपयोग की जाने वाली क्वेरी है:

WITH filtered_messages AS (SELECT * 
                           FROM messages
                           WHERE feed_id IN (7) 
                           AND (posted_at >= '2015-01-01 04:00:00.000000') 
                           AND (posted_at < '2015-04-28 04:00:00.000000'))
    SELECT *
    FROM (SELECT DISTINCT ON(COALESCE(parent_id, message_id)) parent_id,
                          message_id, 
                          posted_at, 
                          share_count
          FROM filtered_messages
          ORDER BY COALESCE(parent_id, message_id), posted_at DESC NULLS LAST
         ) messages
    ORDER BY share_count DESC NULLS LAST, posted_at DESC NULLS LAST;

यहाँ http://sqlfiddle.com/# -15/588e5/1 /0 , SQL Fiddle में, मैंने स्कीमा, सटीक क्वेरी और अपेक्षित परिणाम को परिभाषित किया है।

संदेश तालिका बड़ी हो जाने पर क्वेरी का प्रदर्शन धीमा हो जाता है। मैंने कई सॉर्टिंग इंडेक्स जोड़ने की कोशिश की, लेकिन यह इंडेक्स का उपयोग नहीं करता है। यहाँ व्याख्या है: http://explain.depesz.com/s/Sv2

मैं एक सही सूचकांक कैसे बना सकता हूं?


पहली नज़र ORDER BYमें, उपनगर में पूरी तरह से बेकार है। इसके अलावा, लिंक की गई योजना पोस्ट किए गए क्वेरी का परिणाम नहीं हो सकती है - metadataउदाहरण के लिए, इसका कोई उल्लेख नहीं है ।
dezso

आपका विवरण की भूमिका को कवर नहीं करता feed_idऔर posted_atऔर आप का उल्लेख नहीं था metadataसब पर है, जो एक JSON प्रकार हो रहा है? कृपया इसे सुसंगत बनाने के लिए अपने प्रश्न की मरम्मत करें। आप सीटीई में 500k पंक्तियों का चयन करें ... तालिका में कितनी पंक्तियाँ हैं? आप आमतौर पर सीटीई में कितनी प्रतिशत पंक्तियों का चयन करते हैं? पंक्तियों का प्रतिशत कितना है parent_id IS NULL? प्रदर्शन के प्रश्नों के लिए [postgresql-performance] टैग में जानकारी पर विचार करें ।
इरविन ब्रान्डेसटेटर

यह भी महत्वपूर्ण: प्रत्येक के लिए कितनी पंक्तियाँ parent_id? (मिनट /
एवीजी

क्षमा करें, मैं कुछ स्तंभों को कम करके प्रश्न को अधिक स्पष्ट करने की कोशिश कर रहा था, शेयर_काउंट वास्तव में था metadata। वर्तमान में संदेश तालिका में 10 सैन्य डेटा हैं, लेकिन तेजी से बढ़ रहा है। मुझे लगता है कि प्रत्येक feed_id के लिए विभाजन तालिकाओं में अलग होना चाहिए। चूंकि मैं केवल फ़ीड आईडी प्रति प्राप्त कर रहा हूं। पेरेंट_ड नल बनाम शून्य नहीं का प्रतिशत लगभग 60% / 40% है। एक सामान्य प्रकार की मेज लगभग 1-2% है। (लगभग 100K संदेश) 100K के लिए प्रदर्शन 1s के आसपास है, लेकिन एक बार 500K + करने के लिए यह बिटमैप सूचकांक और सामान्य रूप से 10s का उपयोग करता है।
झौहान वेंग

जवाबों:


9

सवाल

यह क्वेरी किसी भी स्थिति में काफी तेज होनी चाहिए:

SELECT parent_id, message_id, posted_at, share_count
FROM   messages
WHERE  feed_id = 7
AND    posted_at >= '2015-01-01 4:0:0'
AND    posted_at <  '2015-04-28 4:0:0'
AND    parent_id IS NULL  -- match index condition
UNION ALL
(
SELECT DISTINCT ON(parent_id)
       parent_id, message_id, posted_at, share_count
FROM   messages
WHERE  feed_id = 7
AND    posted_at >= '2015-01-01 4:0:0'
AND    posted_at <  '2015-04-28 4:0:0'
AND    parent_id IS NOT NULL  -- match index condition
ORDER  BY parent_id, posted_at DESC NULLS LAST
)
ORDER  BY share_count DESC NULLS LAST, posted_at DESC NULLS LAST;
  • CTE यहाँ कुछ भी नहीं करता है कि एक सादा उपवर्ग भी वितरित नहीं कर सकता है। और एक सीटीई एक अनुकूलन अवरोध का परिचय देता है क्योंकि इसे अलग से निष्पादित किया जाता है और इसका परिणाम भौतिक होता है।

  • आपके पास वास्तव में जरूरत से ज्यादा एक उप-स्तर है।

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

  • parent_id IS NULLएक अलग मामले में सरल मामले को विभाजित करना SELECTया इष्टतम वितरित नहीं कर सकता है। विशेष रूप से नहीं, यदि यह वैसे भी एक दुर्लभ मामला है, तो जिस स्थिति में सूचकांक के साथ एक संयुक्त क्वेरी (COALESCE(parent_id, message_id)बेहतर प्रदर्शन कर सकती है। अन्य विचार लागू होते हैं ...

सूचकांकों

खासकर जब इन सूचकांकों के साथ समर्थन किया जाता है:

CREATE INDEX messages_idx_null ON messages (
  feed_id
, posted_at DESC NULLS LAST
, share_count DESC NULLS LAST
, parent_id, message_id
)
WHERE parent_id IS NULL;

CREATE INDEX messages_idx_notnull ON messages (
  feed_id
, posted_at DESC NULLS LAST
, share_count DESC NULLS LAST
, parent_id, message_id
)
WHERE parent_id IS NOT NULL;

दो आंशिक सूचक पूरे टेबल को एक साथ कवर करते हैं और एक ही आकार के लगभग एक ही सूचकांक के साथ होते हैं।

पिछले दो कॉलम parent_id, message_idकेवल तभी समझ में आते हैं जब आपको इसमें से केवल-इंडेक्स मिलते हैं । दोनों सूचकांकों से उन्हें हटा दें।

एसक्यूएल फिडल।

लापता विवरण के आधार पर, DISTINCT ONइस उद्देश्य के लिए सबसे अच्छी क्वेरी तकनीक हो सकती है या नहीं। विस्तृत विवरण यहां पढ़ें:

और संभवतः यहां तेज विकल्प:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.