जब मैं किसी अनुक्रमणिका स्कैन को करने पर जोर देता हूं तो मैं अनुक्रमणिका का उपयोग करने के लिए कैसे बाध्य करता हूं?
जब मैं किसी अनुक्रमणिका स्कैन को करने पर जोर देता हूं तो मैं अनुक्रमणिका का उपयोग करने के लिए कैसे बाध्य करता हूं?
जवाबों:
यह मानते हुए कि आप कई डेटाबेस में पाए जाने वाले सामान्य "इंडेक्स हिंटिंग" फीचर के बारे में पूछ रहे हैं, PostgreSQL इस तरह की सुविधा प्रदान नहीं करता है। यह PostgreSQL टीम द्वारा किया गया एक सचेत निर्णय था। इसके बजाय आप क्यों और क्या कर सकते हैं, का एक अच्छा अवलोकन यहां पाया जा सकता है । मूल रूप से कारण यह है कि यह एक प्रदर्शन हैक है जो बाद में आपके डेटा में परिवर्तन के रूप में लाइन के नीचे और अधिक समस्याएं पैदा करता है, जबकि पोस्टग्रेजक्यूएल के आशावादी आंकड़ों के आधार पर योजना का पुनर्मूल्यांकन कर सकते हैं। दूसरे शब्दों में, आज एक अच्छी क्वेरी योजना क्या हो सकती है, शायद सभी समय के लिए एक अच्छी क्वेरी योजना नहीं होगी, और सूचकांक संकेत किसी विशेष क्वेरी योजना को हर समय के लिए मजबूर करते हैं।
एक बहुत ही कुंद हथौड़ा के रूप में, परीक्षण के लिए उपयोगी, आप enable_seqscan
और enable_indexscan
मापदंडों का उपयोग कर सकते हैं । देख:
ये चल रहे उत्पादन उपयोग के लिए उपयुक्त नहीं हैं । यदि आपके पास क्वेरी योजना पसंद के साथ समस्याएँ हैं, तो आपको क्वेरी प्रदर्शन समस्याओं को ट्रैक करने के लिए दस्तावेज़ देखना चाहिए । सिर्फ enable_
परम सेट न करें और दूर चलें।
जब तक आपके पास सूचकांक का उपयोग करने का एक बहुत अच्छा कारण नहीं है, तब तक Postgres सही विकल्प बना सकता है। क्यों?
इस पुरानी न्यूज़ग्रुप पोस्ट को भी देखें ।
संभवतः उपयोग करने का एकमात्र मान्य कारण है
set enable_seqscan=false
जब आप प्रश्न लिख रहे हैं और जल्दी से देखना चाहते हैं कि क्वेरी प्लान वास्तव में क्या होगा तो तालिका में बड़ी मात्रा में डेटा थे। या निश्चित रूप से अगर आपको यह जल्दी से पुष्टि करने की आवश्यकता है कि आपकी क्वेरी केवल एक इंडेक्स का उपयोग नहीं कर रही है क्योंकि डेटासेट बहुत छोटा है।
set enable_seqscan=false
, अपनी क्वेरी चलाएँ, और फिर जल्दी set enable_seqscan=true
से अपने उचित व्यवहार के लिए पोस्टग्रैस्कल वापस करने के लिए दौड़ें (और स्पष्ट रूप से उत्पादन में ऐसा नहीं करते हैं, केवल विकास में!)
SET SESSION enable_seqscan=false
केवल अपने आप को प्रभावित करने के लिए
कभी-कभी PostgreSQL किसी विशेष स्थिति के लिए अनुक्रमित का सबसे अच्छा विकल्प बनाने में विफल रहता है। एक उदाहरण के रूप में, मान लें कि कई मिलियन पंक्तियों के साथ एक लेन-देन तालिका है, जिनमें से किसी भी दिन के लिए कई सौ हैं, और तालिका में चार अनुक्रमणिकाएँ हैं: transaction_id, client_id, date और विवरण। आप निम्नलिखित क्वेरी चलाना चाहते हैं:
SELECT client_id, SUM(amount)
FROM transactions
WHERE date >= 'yesterday'::timestamp AND date < 'today'::timestamp AND
description = 'Refund'
GROUP BY client_id
PostgreSQL लेनदेन के बजाय index_description_idx का उपयोग करने का विकल्प चुन सकता है_date_idx, जो क्वेरी को एक मिनट से कम के बजाय कई मिनट ले सकता है। यदि यह मामला है, तो आप इस तरह की स्थिति को ध्यान में रखते हुए सूचकांक पर तारीख का उपयोग करने के लिए मजबूर कर सकते हैं:
SELECT client_id, SUM(amount)
FROM transactions
WHERE date >= 'yesterday'::timestamp AND date < 'today'::timestamp AND
description||'' = 'Refund'
GROUP BY client_id
your_wanted_index
, यह इतना हो सकता है कि पोस्टग्रैक्कल इंजन सिर्फ एक अनुक्रम / प्राथमिक कुंजी स्कैन के बजाय प्रदर्शन करेगा। निष्कर्ष - PostgreSql सर्वर के लिए कुछ इंडेक्स उपयोग को बाध्य करने के लिए कोई 100% विश्वसनीय तरीका नहीं है।
where
स्थिति नहीं है, लेकिन दो टेबल या शामिल हो गए हैं और पोस्टग्रैज इंडेक्स लेने में विफल हैं।
यह समस्या आमतौर पर तब होती है जब एक सूचकांक स्कैन की अनुमानित लागत बहुत अधिक होती है और वास्तविकता को सही ढंग से प्रतिबिंबित नहीं करती है। random_page_cost
इसे ठीक करने के लिए आपको कॉन्फ़िगरेशन पैरामीटर को कम करना पड़ सकता है । से Postgres प्रलेखन :
इस मान को कम करना [...] इस प्रणाली के कारण सूचकांक स्कैन को प्राथमिकता देगा; इसे बढ़ाने से इंडेक्स स्कैन अपेक्षाकृत अधिक महंगे लगेंगे।
आप जांच सकते हैं कि क्या कम मूल्य वास्तव में Postgres सूचकांक का उपयोग करेगा (लेकिन केवल परीक्षण के लिए इसका उपयोग करें ):
EXPLAIN <query>; # Uses sequential scan
SET random_page_cost = 1;
EXPLAIN <query>; # May use index scan now
आप SET random_page_cost = DEFAULT;
फिर से डिफ़ॉल्ट मान को पुनर्स्थापित कर सकते हैं ।
सूचकांक स्कैन के लिए गैर-अनुक्रमिक डिस्क पेज लाने की आवश्यकता होती है। random_page_cost
अनुक्रमिक भ्रूणों के संबंध में ऐसे गैर-अनुक्रमिक भ्रूणों की लागत का अनुमान लगाने के लिए पोस्टग्रेज का उपयोग करता है। डिफ़ॉल्ट मूल्य है 4.0
, इस प्रकार अनुक्रमिक भ्रूण (खाते में कैशिंग प्रभाव को ध्यान में रखते हुए) की तुलना में 4 का औसत लागत कारक माना जाता है ।
समस्या यह है कि यह डिफ़ॉल्ट मान निम्न महत्वपूर्ण वास्तविक जीवन परिदृश्यों में अनुपयुक्त है:
1) सॉलिड-स्टेट ड्राइव
जैसा कि प्रलेखन स्वीकार करता है:
भंडारण जो अनुक्रमिक, जैसे ठोस-राज्य ड्राइव के सापेक्ष कम यादृच्छिक रीड कॉस्ट है, के लिए कम मूल्य के साथ बेहतर मॉडलिंग की जा सकती है
random_page_cost
।
PostgresConf 2018 में एक भाषण से इस स्लाइड के अंतिम बिंदु के अनुसार , ठोस राज्य ड्राइव के random_page_cost
बीच 1.0
और कुछ के लिए सेट किया जाना चाहिए 2.0
।
2) कैश्ड डेटा
यदि आवश्यक इंडेक्स डेटा पहले से ही रैम में कैश्ड है, तो एक इंडेक्स स्कैन हमेशा अनुक्रमिक स्कैन की तुलना में काफी तेज होगा। प्रलेखन कहता है:
इसके विपरीत, यदि आपका डेटा पूरी तरह से कैश में होने की संभावना है, [...] घटाना
random_page_cost
उचित हो सकता है।
समस्या यह है कि आप निश्चित रूप से आसानी से नहीं जान सकते कि संबंधित डेटा पहले से कैश है या नहीं। हालांकि, यदि कोई विशिष्ट इंडेक्स अक्सर क्वेर होता है, और यदि सिस्टम में पर्याप्त रैम है, तो डेटा कैश्ड होने की संभावना है, और random_page_cost
इसे कम मूल्य पर सेट किया जाना चाहिए। आपको विभिन्न मूल्यों के साथ प्रयोग करना होगा और देखना होगा कि आपके लिए क्या काम करता है।
आप स्पष्ट डेटा कैशिंग के लिए pg_prewarm एक्सटेंशन का उपयोग करना चाह सकते हैं ।
स्वयं पर प्रश्न बहुत अमान्य है। मजबूर करना (उदाहरण के लिए enable_seqscan = off करना) बहुत बुरा विचार है। यह जांचने के लिए उपयोगी हो सकता है कि क्या यह तेज होगा, लेकिन उत्पादन कोड को कभी भी ऐसी चाल का उपयोग नहीं करना चाहिए।
इसके बजाय - अपनी क्वेरी का विश्लेषण करें, इसे पढ़ें, और पता करें कि PostgreSQL खराब (आपकी राय में) योजना क्यों चुनता है।
वेब पर ऐसे उपकरण हैं जो पढ़ने में मदद करने के लिए आउटपुट का विश्लेषण करने में मदद करते हैं - उनमें से एक व्याख्या है ।epesz.com - मेरे द्वारा लिखित।
एक अन्य विकल्प #postgresql चैनल पर जुड़ना है freenode irc नेटवर्क , और वहां के लोगों से बात करके आपकी मदद करना है - जैसा कि क्वेरी को अनुकूलित करना "एक सवाल पूछना, जवाब खुश होना" का मामला नहीं है। यह बातचीत की तरह है, कई चीजों को जांचने के लिए, कई चीजों को सीखने के लिए।
वहाँ एक चाल postgres पुश करने के लिए एक seqscan एक जोड़ने पसंद करते हैं करने के लिए है OFFSET 0
सबक्वेरी में
यह बड़े / विशाल तालिकाओं को जोड़ने के अनुरोधों के अनुकूलन के लिए आसान है जब आपको केवल आवश्यक पहले / अंतिम तत्वों की आवश्यकता होती है।
कहते हैं कि आप पहले / अंतिम 20 तत्वों की तलाश कर रहे हैं जिसमें 100k (या अधिक) प्रविष्टियां होने वाली कई तालिकाएँ शामिल हैं, कोई बिंदु निर्माण / सभी डेटा पर सभी क्वेरी को जोड़ना जब आप जो देख रहे हैं वह पहले 100 या 1000 में होगा प्रविष्टियों। इस परिदृश्य में उदाहरण के लिए, यह क्रमिक स्कैन करने के लिए 10x से अधिक तेजी से निकलता है।
देखें कि मैं पोस्टग्रेज को एक उपनगरीय इलाके में घुसने से कैसे रोक सकता हूं?