2012-02-28 10 views
8

में सूचकांक का उपयोग नहीं मैं कुछ अजीब/अजीब देख रहा हूँ: एक ही क्वेरी पथ का उपयोग नहीं कर रहे हैंPostgreSQL क्वेरी उत्पादन

में विकास/उत्पादन ठीक उसी क्वेरी। विशेष रूप से, विकास संस्करण इंडेक्स का उपयोग कर रहा है जो उत्पादन में छोड़े जाते हैं (seqscan के पक्ष में)।

एकमात्र वास्तविक अंतर यह है कि डेटासेट उत्पादन काफी बड़ा है - सूचकांक आकार 1034 एमबी है, उत्पादन में 2 9 एमबी बनाम है। क्या PostgreSQL इंडेक्स का उपयोग करने से दूर रहेंगे यदि वे (या तालिका) बहुत बड़े हैं?

संपादित करें: दोनों प्रश्नों के लिए EXPLAIN ANALYZE:

विकास:

Limit (cost=41638.15..41638.20 rows=20 width=154) (actual time=159.576..159.581 rows=20 loops=1) 
    -> Sort (cost=41638.15..41675.10 rows=14779 width=154) (actual time=159.575..159.577 rows=20 loops=1) 
     Sort Key: (sum(scenario_ad_group_performances.clicks)) 
     Sort Method: top-N heapsort Memory: 35kB 
     -> GroupAggregate (cost=0.00..41244.89 rows=14779 width=154) (actual time=0.040..151.535 rows=14197 loops=1) 
       -> Nested Loop Left Join (cost=0.00..31843.75 rows=93800 width=154) (actual time=0.022..82.509 rows=50059 loops=1) 
        -> Merge Left Join (cost=0.00..4203.46 rows=14779 width=118) (actual time=0.017..27.103 rows=14197 loops=1) 
          Merge Cond: (scenario_ad_groups.id = scenario_ad_group_vendor_instances.ad_group_id) 
          -> Index Scan using scenario_ad_groups_pkey on scenario_ad_groups (cost=0.00..2227.06 rows=14779 width=114) (actual time=0.009..12.085 rows=14197 loops=1) 
           Filter: (scenario_id = 22) 
          -> Index Scan using index_scenario_ad_group_vendor_instances_on_ad_group_id on scenario_ad_group_vendor_instances (cost=0.00..1737.02 rows=27447 width=8) (actual time=0.007..7.021 rows=16528 loops=1) 
           Filter: (ad_vendor_id = ANY ('{1,2,3}'::integer[])) 
        -> Index Scan using index_ad_group_performances_on_vendor_instance_id_and_date on scenario_ad_group_performances (cost=0.00..1.73 rows=11 width=44) (actual time=0.002..0.003 rows=3 loops=14197) 
          Index Cond: ((vendor_instance_id = scenario_ad_group_vendor_instances.id) AND (date >= '2012-02-01'::date) AND (date <= '2012-02-28'::date)) 
Total runtime: 159.710 ms 

उत्पादन:

Limit (cost=822401.35..822401.40 rows=20 width=179) (actual time=21279.547..21279.591 rows=20 loops=1) 
    -> Sort (cost=822401.35..822488.42 rows=34828 width=179) (actual time=21279.543..21279.560 rows=20 loops=1) 
     Sort Key: (sum(scenario_ad_group_performances.clicks)) 
     Sort Method: top-N heapsort Memory: 33kB 
     -> GroupAggregate (cost=775502.60..821474.59 rows=34828 width=179) (actual time=19126.783..21226.772 rows=34495 loops=1) 
       -> Sort (cost=775502.60..776739.48 rows=494751 width=179) (actual time=19125.902..19884.164 rows=675253 loops=1) 
        Sort Key: scenario_ad_groups.id 
        Sort Method: external merge Disk: 94200kB 
        -> Hash Right Join (cost=25743.86..596796.70 rows=494751 width=179) (actual time=1155.491..16720.460 rows=675253 loops=1) 
          Hash Cond: (scenario_ad_group_performances.vendor_instance_id = scenario_ad_group_vendor_instances.id) 
          -> Seq Scan on scenario_ad_group_performances (cost=0.00..476354.29 rows=4158678 width=44) (actual time=0.043..8949.640 rows=4307019 loops=1) 
           Filter: ((date >= '2012-02-01'::date) AND (date <= '2012-02-28'::date)) 
          -> Hash (cost=24047.72..24047.72 rows=51371 width=143) (actual time=1123.896..1123.896 rows=34495 loops=1) 
           Buckets: 1024 Batches: 16 Memory Usage: 392kB 
           -> Hash Right Join (cost=6625.90..24047.72 rows=51371 width=143) (actual time=92.257..1070.786 rows=34495 loops=1) 
             Hash Cond: (scenario_ad_group_vendor_instances.ad_group_id = scenario_ad_groups.id) 
             -> Seq Scan on scenario_ad_group_vendor_instances (cost=0.00..11336.31 rows=317174 width=8) (actual time=0.020..451.496 rows=431770 loops=1) 
              Filter: (ad_vendor_id = ANY ('{1,2,3}'::integer[])) 
             -> Hash (cost=5475.55..5475.55 rows=34828 width=139) (actual time=88.311..88.311 rows=34495 loops=1) 
              Buckets: 1024 Batches: 8 Memory Usage: 726kB 
              -> Bitmap Heap Scan on scenario_ad_groups (cost=798.20..5475.55 rows=34828 width=139) (actual time=4.451..44.065 rows=34495 loops=1) 
                Recheck Cond: (scenario_id = 276) 
                -> Bitmap Index Scan on index_scenario_ad_groups_on_scenario_id (cost=0.00..789.49 rows=34828 width=0) (actual time=4.232..4.232 rows=37006 loops=1) 
                 Index Cond: (scenario_id = 276) 
Total runtime: 21306.697 ms 
+0

सूचकांक आपके उत्पादन वातावरण में पर्याप्त नहीं हो सकता है –

+0

"पर्याप्त चुनिंदा नहीं" का क्या अर्थ है? – vonconrad

+1

यदि आपके पास एक अनुक्रमित बूलियन कॉलम है जहां 99% डेटा 'झूठा' है, तो इंडेक्स स्कैन करने और फिर तालिका का 99% स्कैन करने में बहुत अधिक बिंदु नहीं है, बल्कि पूरे टेबल को स्कैन करने के विरुद्ध। इंडेक्स 'झूठी' मानों के लिए पर्याप्त नहीं होगा। – aib

उत्तर

13

अस्वीकरण

मैं PostgreSQL बहुत कम इस्तेमाल किया है। मैं SQL सर्वर इंडेक्स उपयोग और निष्पादन योजनाओं के बारे में अपने ज्ञान के आधार पर जवाब दे रहा हूं। अगर मैं कुछ गलत करता हूं तो मैं दया के लिए PostgreSQL देवताओं से प्रार्थना करता हूं।

क्वेरी Optimizers गतिशील

तुमने कहा था आपकी क्वेरी योजना उत्पादन वातावरण के लिए अपने विकास से बदल गया है कर रहे हैं। इसकी उम्मीद की जा रही है। क्वेरी ऑप्टिमाइज़र को वर्तमान डेटा स्थितियों के आधार पर इष्टतम निष्पादन योजना उत्पन्न करने के लिए डिज़ाइन किया गया है। विभिन्न स्थितियों के तहत ऑप्टिमाइज़र यह तय कर सकता है कि एक तालिका स्कैन बनाम इंडेक्स स्कैन का उपयोग करना अधिक कुशल है।

जब इसे और अधिक एक सूचकांक बनाम एक मेज स्कैन का उपयोग करने के कुशल स्कैन किया जाएगा?

SELECT A, B 
FROM someTable 
WHERE A = 'SOME VALUE' 

मान लीजिए कि आप स्तंभ A पर एक गैर क्लस्टर सूचकांक करते हैं। इस मामले में आप कॉलम A पर फ़िल्टर कर रहे हैं, जो संभावित रूप से सूचकांक का लाभ उठा सकता है। यह प्रभावी होगा अगर सूचकांक पर्याप्त चुनिंदा है - मूल रूप से, कितने अलग मूल्य सूचकांक बनाते हैं? डेटाबेस इस चुनिंदा जानकारी पर आंकड़े रखता है और निष्पादन योजनाओं के लिए लागत की गणना करते समय इन आंकड़ों का उपयोग करता है।

आप एक तालिका में एक लाख पंक्तियाँ, लेकिन A के लिए केवल 10 संभावित मान है, तो आपकी क्वेरी की संभावना के बारे में 100K पंक्तियों को वापस करेगा। क्योंकि सूचकांक है गैर क्लस्टर, और आप सूचकांक, B में शामिल नहीं कॉलम लौट रहे हैं, एक देखने प्रत्येक पंक्ति लौटे के लिए प्रदर्शन करने की आवश्यकता होगी। ये लुक-अप यादृच्छिक-पहुंच लुकअप हैं जो तालिका स्कैन द्वारा उपयोग किए जाने वाले अनुक्रमिक पढ़ने के बाद अधिक महंगे होते हैं। एक निश्चित बिंदु पर यह डेटाबेस के लिए इंडेक्स स्कैन की बजाय टेबल स्कैन करने के लिए अधिक कुशल हो जाता है।

यह सिर्फ एक परिदृश्य है, वहाँ कई अन्य हैं। यह क्या आपके डेटा की तरह है, जो आपके अनुक्रमित की तरह लग रही है और आप कैसे डेटा का उपयोग करने की कोशिश कर रहे के बारे में अधिक जानने के बिना पता करने के लिए मुश्किल है।

चाहेंगे PostgreSQL अनुक्रमित का उपयोग करने से बचना अगर वे (या तालिका) बहुत बड़े हैं:

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

PostgreSQL पूछे जाने वाले प्रश्न पर छू लेती है यह बहुत ही विषय (देखें: क्यों मेरी प्रश्नों धीमी गति से कर रहे हैं क्यों कि वे मेरी अनुक्रमित का उपयोग नहीं करते?): https://wiki.postgresql.org/wiki/FAQ#Why_are_my_queries_slow.3F_Why_don.27t_they_use_my_indexes.3F

+0

विकी पेज बहुत अच्छा है। – Benoit

+0

अंतिम लिंक टूटा हुआ है - काम करने वाला लिंक: https://wiki.postgresql.org/wiki/FAQ#Why_are_my_queries_slow.3F_Why_don.27t_they_use_my_indexes.3F – dmikam

+0

बहुत ही बोल्ड उस तरह के अस्वीकरण के साथ एक उत्तर शुरू कर रहा है! – jwg2s

3

Postgres 'क्वेरी अनुकूलक अनेक परिदृश्यों में आता है (उदाहरण के लिए इंडेक्स बनाम सीक-स्कैन) और कॉन्फ़िगरेशन में डिस्क/मेमोरी/इंडेक्स/टेबल एक्सेस सेट की सापेक्ष लागतों के बारे में सांख्यिकीय जानकारी का उपयोग करके उनका मूल्यांकन करता है।

क्या आपने EXPLAIN कमांड का उपयोग यह देखने के लिए किया था कि क्यों इंडेक्स उपयोग छोड़ा गया था? क्या निर्णय में त्रुटि हुई है या नहीं, यह पता लगाने के लिए आपने EXPLAIN ANALYZE का उपयोग किया था? क्या हम आउटपुट देख सकते हैं, कृपया?

संपादित करें:

के रूप में कठिन विभिन्न प्रणालियों पर दो अलग-अलग विलक्षण प्रश्नों का विश्लेषण करने के रूप में कर रहे हैं, मुझे लगता है कि मैं चीजों के एक जोड़े को देखते हैं।

उत्पादन वातावरण में प्रति लागत इकाई के लगभग 20-100 मिलीसेकंड की वास्तविक/लागत दर है। मैं भी एक डीबीए नहीं हूं, लेकिन यह लगातार लगता है। मुख्य प्रश्न के लिए विकास पर्यावरण में 261 है। क्या यह सही लगता है? क्या आप उत्पादन पर्यावरण की कच्ची गति (मेमोरी/डिस्क/सीपीयू) देव से 2-10x तेज होने की अपेक्षा करेंगे?

चूंकि उत्पादन वातावरण में अधिक जटिल क्वेरी योजना है, ऐसा लगता है कि यह अपना काम कर रहा है। निस्संदेह, देव पर्यावरण की योजना और कई पर विचार किया गया है, और बहुत महंगा माना जाता है। और 20-100 भिन्नता मेरे अनुभव में इतना नहीं है (लेकिन फिर, एक डीबीए नहीं) और दिखाती है कि निशान से कुछ भी रास्ता नहीं है। फिर भी, आप मामले में डीबी पर VACUUM चला सकते हैं।

मैं पूर्ण क्वेरी को डीकोड करने के लिए पर्याप्त अनुभवी और धीरज नहीं हूं, लेकिन अनुकूलन के लिए एक denormalization/NOSQL-ization बिंदु हो सकता है?

सबसे बड़ी बाधा 90 एमबी पर डिस्क विलय प्रतीत होती है। अगर उत्पादन वातावरण में पर्याप्त स्मृति है, तो आप इसे स्मृति में करने के लिए प्रासंगिक सेटिंग (काम कर रहे स्मृति?) को बढ़ाना चाह सकते हैं। ऐसा लगता है कि यह work_mem पैरामीटर here है, हालांकि आप बाकी के माध्यम से पढ़ना चाहते हैं।

मैं पर पर भी सुझाव देना चाहता हूं। आंशिक और कार्यात्मक सूचकांक के साथ कई विकल्प मौजूद हैं।

+0

मेरे प्रश्न को 'EXPLAIN ANALYZE' आउटपुट के साथ संपादित किया गया। – vonconrad

3

प्रयास करें

SET enable_seqscan TO 'off' 

EXPLAIN ANALYZE से पहले

+9

ध्यान दें कि यदि आपने समझाया कि यह समस्या निवारण तकनीक है यह निर्धारित करने के लिए कि वास्तव में क्वेरी को डेटाबेस के लिए अंधाधुंध रूप से लागू करने के लिए एक इंडेक्स स्कैन के साथ तेज़ होगा, तो यह एक बेहतर जवाब होगा। –

2

मुझे ऐसा लगता है कि आपके देव डेटा ज्यादा उत्पादन डेटा की तुलना में "सरल" है। एक उदाहरण के रूप:

विकास:

-> Index Scan using index_scenario_ad_group_vendor_instances_on_ad_group_id on scenario_ad_group_vendor_instances 
(cost=0.00..1737.02 rows=27447 width=8) 
(actual time=0.007..7.021 rows=16528 loops=1) 
Filter: (ad_vendor_id = ANY ('{1,2,3}'::integer[])) 

उत्पादन:

-> Seq Scan on scenario_ad_group_vendor_instances 
(cost=0.00..11336.31 rows=317174 width=8) 
(actual time=0.020..451.496 rows=431770 loops=1) 
Filter: (ad_vendor_id = ANY ('{1,2,3}'::integer[])) 

इसका मतलब यह है, कि में देव 27,447 मिलान पंक्ति अग्रिम अनुमान के अनुसार किया गया है और 16528 पंक्तियों वास्तव में पाए गए। वह वही ballpark और ठीक नहीं है।

उत्पादन में 317174 मिलान पंक्तियों का अनुमान लगाया गया है और 431770 पंक्तियां मिलीं। यह भी ठीक है।

लेकिन प्रोड से देव की तुलना करना मतलब है कि संख्या 10 गुना अलग है। जैसा कि पहले से ही अन्य उत्तरों इंगित करते हैं, 10 गुना अधिक यादृच्छिक खोज (इंडेक्स एक्सेस के कारण) वास्तव में एक सादे टेबल स्कैन से भी बदतर हो सकता है।

इसलिए दिलचस्प सवाल यह है कि इस तालिका में देव और प्रोड दोनों में कितनी पंक्तियां हैं? number_returned_rows/number_total_rows देव और प्रोड के बीच तुलनीय है?

संपादित मत भूलना: मैं एक उदाहरण के रूप एक सूचकांक पहुँच चुना है। एक त्वरित नज़र से पता चलता है कि अन्य इंडेक्स एक्सेसों में समान लक्षण हैं।