2013-07-10 3 views
8

मेरे पास पोस्टग्रेस्क्ल 9.2 सिस्टम पर एक क्वेरी है जो इसके सामान्य रूप में लगभग 20s लेती है लेकिन सीटीई का उपयोग करते समय केवल ~ 120ms लेती है।क्या सीटीई का उपयोग किये बिना इस प्रश्न का तार्किक रूप से समतुल्य और कुशल संस्करण है?

मैंने ब्रेवटी के लिए दोनों प्रश्नों को सरल बनाया।

यहाँ सामान्य रूप है (20 के बारे में लेता है): http://explain.depesz.com/s/2v8

CTE प्रपत्र (के बारे में 120ms):

WITH raw AS (
    SELECT * 
    FROM tableA 
    WHERE (columna = 1 OR columnb = 2) AND 
     atype = 35 AND 
     aid IN (1, 2, 3) 
) 
SELECT * 
FROM raw 
ORDER BY modified_at DESC 
LIMIT 25; 

SELECT * 
FROM tableA 
WHERE (columna = 1 OR columnb = 2) AND 
    atype = 35 AND 
    aid IN (1, 2, 3) 
ORDER BY modified_at DESC 
LIMIT 25; 

यहाँ इस प्रश्न के लिए समझाने है सीटीई के लिए यहां बताया गया है: http://explain.depesz.com/s/uxy

बस चलकर ORDER BY क्वेरी के बाहरी हिस्से में 99% की लागत कम कर देता है।

मेरे पास दो प्रश्न हैं: 1) सीटीई का उपयोग किए बिना पहली क्वेरी बनाने का कोई तरीका है कि यह तर्कसंगत रूप से अधिक प्रदर्शन करने वाला है और 2) प्रदर्शन में यह अंतर क्या कहता है कि योजनाकार कैसे है डेटा लाने के लिए निर्धारित करना?

उपरोक्त प्रश्नों के बारे में, क्या अतिरिक्त आंकड़े या अन्य योजनाकार संकेत हैं जो पहली क्वेरी के प्रदर्शन में सुधार करने में मदद करेंगे?


संपादित करें: सीमा को दूर करने से क्वेरी को एक इंडेक्स स्कैन के विपरीत एक हीप स्कैन का उपयोग करने का कारण बनता है। LIMIT के बिना क्वेरी 40ms में पूर्ण हो जाती है।

आदि LIMIT के प्रभाव मैं LIMIT 1 साथ की कोशिश की, LIMIT 2, देखने के बाद क्वेरी जब LIMIT 1 और 10s + LIMIT> 1.

साथ उपयोग करते हुए इस में कुछ और, सवाल 2 फोड़े के बारे में सोच करने के बाद 100ms के तहत में प्रदर्शन प्लानर एक मामले में पीछे एक इंडेक्स स्कैन का उपयोग क्यों करता है और बिटमैप हीप स्कैन + किसी अन्य तर्कसंगत समकक्ष मामले में सॉर्ट करता है? और प्लानर दोनों मामलों में कुशल योजना का उपयोग करने में "सहायता" कैसे कर सकता हूं?


अद्यतन: मैं क्रेग की जवाब स्वीकार किए जाते हैं, क्योंकि यह सबसे व्यापक और मददगार था। जिस तरह से मैंने समस्या को हल करने का अंत किया था, वह एक क्वेरी का उपयोग करके व्यावहारिक रूप से समकक्ष था, हालांकि तर्कसंगत समकक्ष नहीं था। इस मुद्दे की जड़ पर संशोधित_एट पर सूचकांक के पीछे एक सूचकांक स्कैन था। योजनाकार को सूचित करने के लिए कि यह एक अच्छा विचार नहीं था, मैं WHERE modified_at >= NOW() - INTERVAL '1 year' रूप का एक अनुमान जोड़ता हूं। इसमें एप्लिकेशन के लिए पर्याप्त डेटा शामिल था लेकिन प्लानर को पिछड़ा इंडेक्स स्कैन पथ नीचे जाने से रोका।

यह एक बहुत कम प्रभाव समाधान था जो उप-क्वेरी या सीटीई का उपयोग कर क्वेरी को फिर से लिखने की आवश्यकता को रोकता था। YMMV।

उत्तर

10

यहाँ क्यों इस निम्नलिखित विवरण वर्तमान के साथ, हो रहा है कम से कम 9 तक है।3 (यदि आप इसे और एक नए संस्करण पर पढ़ रहे हैं, तो यह सुनिश्चित करने के लिए जांचें कि यह नहीं बदला गया है):

PostgreSQL सीटीई सीमाओं में अनुकूल नहीं है। प्रत्येक सीटीई खंड अलगाव में चलाया जाता है और इसके परिणाम क्वेरी के अन्य हिस्सों से खपत होते हैं। तो एक प्रश्न जैसे:

WITH blah AS (
    SELECT * FROM some_table 
) 
SELECT * 
FROM blah 
WHERE id = 4; 

पूर्ण आंतरिक क्वेरी निष्पादित करने का कारण बन जाएगा। PostgreSQL आंतरिक क्वेरी में id = 4 योग्यता को "धक्का" नहीं देगा। उस संबंध में सीटीई "अनुकूलन बाड़" हैं, जो दोनों अच्छे या बुरे हो सकते हैं; यह आपको प्लानर को ओवरराइड करने देता है, लेकिन जब आप पुश-डाउन की आवश्यकता होती है तो आपको सीटीई को गहरा घोंसला FROM सबक्वायरी श्रृंखला के लिए सरल वाक्यविन्यास क्लीनअप के रूप में उपयोग करने से रोकती है।

यदि आपने उपरोक्त अलग तरीके से व्यक्त करते हैं: एक CTE के बजाय FROM में एक सबक्वेरी का उपयोग कर

SELECT * 
FROM (SELECT * FROM some_table) AS blah 
WHERE id = 4; 

, पृष्ठ सबक्वेरी में qual नीचे आ जाएगी और यह सब अच्छा चलाने के लिए और जल्दी से होगा।

जैसा कि आपने पाया है, यह क्वेरी प्लानर खराब निर्णय लेने पर भी आपके लाभ के लिए काम कर सकता है। ऐसा लगता है कि आपके मामले में तालिका का पिछड़ा सूचकांक स्कैन बेहद अधिक महंगा है और दो छोटे इंडेक्स के सूचकांक स्कैन को फ़िल्टर और सॉर्ट के बाद, लेकिन योजनाकार को नहीं लगता कि यह होगा, इसलिए यह क्वेरी की योजना है सूचकांक स्कैन करने के लिए।

जब आप सीटीई का उपयोग करते हैं, तो यह ORDER BY को आंतरिक क्वेरी में धक्का नहीं दे सकता है, इसलिए आप अपनी योजना को ओवरराइड कर रहे हैं और इसे समझने के लिए मजबूर कर रहे हैं जो एक कम निष्पादन योजना है - लेकिन जो एक हो जाता है काफी बेहतर।

एक खराब कामकाज है जिसका उपयोग OFFSET 0 हैक नामक इन परिस्थितियों के लिए किया जा सकता है, लेकिन आपको केवल इसका उपयोग करना चाहिए यदि आप योजनाकार को सही काम करने का कोई तरीका नहीं समझ सकते - और यदि आपको उपयोग करना है इसे, कृपया इसे स्वयं निहित परीक्षण केस में उबालें और इसे संभावित क्वेरी प्लानर बग के रूप में PostgreSQL मेलिंग सूची में रिपोर्ट करें।

इसके बजाय, मैं पहले पर विचार करने की सलाह देता हूं क्यों योजनाकार गलत निर्णय ले रहा है।

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

मुख्य मुद्दा लगता है कि यह है क्योंकि यह ORDER BY देखता नहीं छोटे, अधिक चयनात्मक अनुक्रमणिका का उपयोग कर sierra_kilo और papa_lima और सोचता है कि यह अधिक समय एक पिछड़े सूचकांक स्कैन करने और तरह से परहेज की तुलना में यह वास्तव में करता बचा सकते हैं । यह समझ में आता है कि क्रमबद्ध करने के लिए केवल एक मिलान पंक्ति है! अगर इसे 3500 पंक्तियों की उम्मीद है तो यह इस तरह से बचने के लिए और अधिक समझदार हो सकता है, हालांकि यह स्मृति में बस क्रमबद्ध करने के लिए अभी भी काफी छोटी पंक्ति है।

क्या आप enable_seqscan, आदि जैसे कोई पैरामीटर सेट करते हैं? यदि आप करते हैं, तो उन्हें अनसेट करें; वे के लिए केवल परीक्षण कर रहे हैं और उत्पादन के उपयोग के लिए पूरी तरह अनुचित हैं।यदि आप enable_ पैराम्स का उपयोग नहीं कर रहे हैं तो मुझे लगता है कि यह PostgreSQL मेलिंग सूची pgsql-perform पर इसे बढ़ाने के लायक है। अनामित योजनाएं इसे थोड़ा मुश्किल बनाती हैं, हालांकि, विशेष रूप से जब कोई गारंटी नहीं है कि एक योजना से पहचानकर्ता अन्य योजनाओं में एक ही वस्तु को संदर्भित करते हैं, और वे प्रश्न पर पूछे गए प्रश्नों से मेल नहीं खाते हैं। आप मेलिंग सूची पर पूछने से पहले सबकुछ ठीक से हाथ से किए गए संस्करण का उत्पादन करना चाहते हैं।

एक अच्छा मौका है कि आपको किसी भी मदद के लिए वास्तविक मान प्रदान करने की आवश्यकता होगी। यदि आप सार्वजनिक मेलिंग सूची, there's another option available पर ऐसा नहीं करना चाहते हैं। (मुझे ध्यान रखना चाहिए कि मैं उनमें से एक के लिए काम करता हूं, मेरी प्रोफाइल के अनुसार)।

+0

धन्यवाद, हालांकि मैंने इस संपत्ति का लाभ उठाया है (यह बिंदु में एक मामला है) मुझे नहीं पता था कि PostgreSQL सीटीई सीमाओं में अनुकूल नहीं है। यदि आप प्रदान की गई समझाई गई योजनाओं को देखते हैं, तो ऐसा नहीं लगता है कि 'work_mem' की महत्वपूर्ण मात्रा का उपयोग किया जा रहा है (~ 25k)। अधिकांश लागत इंडेक्स स्कैन से पीछे की ओर आ रही है। – drsnyder

+0

@drsnyder ओह! मैंने गलत पढ़ लिया! 20s और 120ms। मैं उचित उत्तर को फिर से पढ़ और समायोजित कर दूंगा। –

+0

@drsnyder पुनः लिखित। उम्मीद है कि अधिक समझ में आता है। कृपया http://wiki.postgresql.org/wiki/Server_Configuration के आउटपुट को केवल यह पुष्टि करने के लिए दिखाएं कि आपके पास कोई 'enable_' पैराम, आदि नहीं है, लेकिन यह योजनाकार द्वारा थोड़ी सी पसंद की तरह दिखता है। –

2

अंधेरे में बस एक गोली मार दी है, लेकिन क्या होता है अगर आप को चलाने के इस

SELECT * 
FROM (
    SELECT * 
    FROM tableA 
    WHERE (columna = 1 OR columnb = 2) AND 
     atype = 35 AND 
     aid IN (1, 2, 3) 
) AS x 
ORDER BY modified_at DESC 
LIMIT 25; 
संबंधित मुद्दे

 संबंधित मुद्दे