2013-02-20 41 views
23

क्यों "में" ऑपरेटर जब सबक्वेरी के साथ प्रयोग किया इतनी धीमी गति से है के साथ ऑपरेटर में?PostgreSQL सबक्वेरी खराब प्रदर्शन

select * 
from view1 
where id in (1,2,3,4,5,6,7,8,9,10) 
order by somedata; 

9ms में निष्पादित करता है।

select * 
from view1 
where id in (select ext_id 
      from aggregate_table 
      order by somedata limit 10) 
order by somedata; 

25000ms में निष्पादित करता है और (view1) पहली क्वेरी में करता है के रूप में सबक्वेरी द्वारा लौटाए गए प्राथमिक कुंजी पर सूचकांक स्कैन देखने के बजाय पर अनुक्रमिक स्कैन का उपयोग करने लगता है।

सबक्वेरी select ext_id from aggregate_table order by somedata limit 10 0.1ms

तो दूसरा क्वेरी की सुस्ती की दृष्टि तीन यूनियनों युक्त है और के बारे में तीन प्रत्येक यूनिअन में जुड़ जो view1 पर अनुक्रमिक स्कैन के कारण होता है में निष्पादित करता है। पहले यूनियन में 1 एम पंक्तियां होती हैं, अन्य बहुत कम होती हैं। कुछ 100K पंक्तियों के साथ तालिकाओं के साथ जुड़ता है। यह इतना प्रासंगिक नहीं है, हालांकि, मैं बस ऑपरेटर व्यवहार को समझना चाहता था।

जो मैं पूरा करने की कोशिश कर रहा हूं वह सबक्वायरी (प्राथमिक कुंजी का एक सेट) का परिणाम लेना और जटिल दृश्य (view1) से डेटा का चयन करना है।

मैं भी

select v1.* 
from view1 v1, 
    aggregate_table at 
where v1.id = at.ext_id 
order by at.somedata 
limit 10 

उपयोग नहीं कर सकते, क्योंकि मैं बड़ा somedata द्वारा में शामिल होने सॉर्ट करने के लिए नहीं करना चाहती। मैं केवल प्राथमिक कुंजी द्वारा दृश्य से 10 परिणाम चुनना चाहता हूं और फिर केवल इन्हें सॉर्ट करना चाहता हूं।

सवाल यह है कि जब मैं स्पष्ट रूप से इन कुंजियों की सूची क्यों ऑपरेटर में करता है तेजी से प्रदर्शन करते हैं और इतनी धीमी गति से जब मैं एक तेजी से सबक्वेरी कि चाबियों का ठीक उसी सेट देता है का उपयोग करें? select * from view1 where id in (1,2,3,4,5,6,7,8,9,10) order by somedata;

Sort (cost=348.480..348.550 rows=30 width=943) (actual time=14.385..14.399 rows=10 loops=1) 
    Sort Key: "india".three 
    Sort Method: quicksort Memory: 30kB 
    -> Append (cost=47.650..347.440 rows=30 width=334) (actual time=11.528..14.275 rows=10 loops=1) 
     -> Subquery Scan "*SELECT* 1" (cost=47.650..172.110 rows=10 width=496) (actual time=11.526..12.301 rows=10 loops=1) 
       -> Nested Loop (cost=47.650..172.010 rows=10 width=496) (actual time=11.520..12.268 rows=10 loops=1) 
        -> Hash Join (cost=47.650..87.710 rows=10 width=371) (actual time=11.054..11.461 rows=10 loops=1) 
          Hash Cond: (hotel.alpha_five = juliet_xray.alpha_five) 
          -> Bitmap Heap Scan on sierra hotel (cost=42.890..82.800 rows=10 width=345) (actual time=10.835..11.203 rows=10 loops=1) 
            Recheck Cond: (four = ANY ('quebec'::integer[])) 
           -> Bitmap Index Scan on seven (cost=0.000..42.890 rows=10 width=0) (actual time=0.194..0.194 rows=10 loops=1) 
             Index Cond: (four = ANY ('quebec'::integer[])) 
          -> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.184..0.184 rows=34 loops=1) 
           -> Seq Scan on six juliet_xray (cost=0.000..4.340 rows=34 width=30) (actual time=0.029..0.124 rows=34 loops=1) 
        -> Index Scan using charlie on juliet_two zulu (cost=0.000..8.390 rows=1 width=129) (actual time=0.065..0.067 rows=1 loops=10) 
          Index Cond: (zulu.four = hotel.victor_whiskey) 
     -> Subquery Scan "*SELECT* 2" (cost=4.760..97.420 rows=10 width=366) (actual time=0.168..0.168 rows=0 loops=1) 
       -> Hash Join (cost=4.760..97.320 rows=10 width=366) (actual time=0.165..0.165 rows=0 loops=1) 
         Hash Cond: (alpha_xray.alpha_five = juliet_xray2.alpha_five) 
        -> Nested Loop (cost=0.000..92.390 rows=10 width=340) (actual time=0.162..0.162 rows=0 loops=1) 
          -> Seq Scan on lima_echo alpha_xray (cost=0.000..8.340 rows=10 width=216) (actual time=0.159..0.159 rows=0 loops=1) 
            Filter: (four = ANY ('quebec'::integer[])) 
          -> Index Scan using charlie on juliet_two xray (cost=0.000..8.390 rows=1 width=128) (never executed) 
            Index Cond: (zulu2.four = alpha_xray.victor_whiskey) 
        -> Hash (cost=4.340..4.340 rows=34 width=30) (never executed) 
          -> Seq Scan on six uniform (cost=0.000..4.340 rows=34 width=30) (never executed) 
     -> Subquery Scan "*SELECT* 3" (cost=43.350..77.910 rows=10 width=141) (actual time=1.775..1.775 rows=0 loops=1) 
       -> Hash Join (cost=43.350..77.810 rows=10 width=141) (actual time=1.771..1.771 rows=0 loops=1) 
         Hash Cond: (golf.alpha_five = juliet_xray3.alpha_five) 
        -> Bitmap Heap Scan on lima_golf golf (cost=38.590..72.910 rows=10 width=115) (actual time=0.110..0.110 rows=0 loops=1) 
          Recheck Cond: (four = ANY ('quebec'::integer[])) 
          -> Bitmap Index Scan on victor_hotel (cost=0.000..38.590 rows=10 width=0) (actual time=0.105..0.105 rows=0 loops=1) 
            Index Cond: (four = ANY ('quebec'::integer[])) 
        -> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.118..0.118 rows=34 loops=1) 
          -> Seq Scan on six victor_kilo (cost=0.000..4.340 rows=34 width=30) (actual time=0.007..0.063 rows=34 loops=1) 
Total runtime: 14.728 ms 

दूसरा प्रश्न - - select * from view1 where id in (select ext_id from aggregate_table order by somedata limit 10) order by somedata;

Sort (cost=254515.780..254654.090 rows=55325 width=943) (actual time=24687.475..24687.488 rows=10 loops=1) 
    Sort Key: "five".xray_alpha 
    Sort Method: quicksort Memory: 30kB 
    -> Hash Semi Join (cost=54300.820..250157.370 rows=55325 width=943) (actual time=11921.783..24687.308 rows=10 loops=1) 
      Hash Cond: ("five".lima = "delta_echo".lima) 
     -> Append (cost=54298.270..235569.720 rows=1106504 width=494) (actual time=3412.453..23091.938 rows=1106503 loops=1) 
       -> Subquery Scan "*SELECT* 1" (cost=54298.270..234227.250 rows=1100622 width=496) (actual time=3412.450..20234.122 rows=1100622 loops=1) 
        -> Hash Join (cost=54298.270..223221.030 rows=1100622 width=496) (actual time=3412.445..17078.021 rows=1100622 loops=1) 
          Hash Cond: (three_victor.xray_hotel = delta_yankee.xray_hotel) 
          -> Hash Join (cost=54293.500..180567.160 rows=1100622 width=470) (actual time=3412.251..12108.676 rows=1100622 loops=1) 
            Hash Cond: (three_victor.tango_three = quebec_seven.lima) 
           -> Seq Scan on india three_victor (cost=0.000..104261.220 rows=1100622 width=345) (actual time=0.015..3437.722 rows=1100622 loops=1) 
           -> Hash (cost=44613.780..44613.780 rows=774378 width=129) (actual time=3412.031..3412.031 rows=774603 loops=1) 
             -> Seq Scan on oscar quebec_seven (cost=0.000..44613.780 rows=774378 width=129) (actual time=4.142..1964.036 rows=774603 loops=1) 
          -> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.149..0.149 rows=34 loops=1) 
           -> Seq Scan on alpha_kilo delta_yankee (cost=0.000..4.340 rows=34 width=30) (actual time=0.017..0.095 rows=34 loops=1) 
       -> Subquery Scan "*SELECT* 2" (cost=4.760..884.690 rows=104 width=366) (actual time=7.846..10.161 rows=104 loops=1) 
        -> Hash Join (cost=4.760..883.650 rows=104 width=366) (actual time=7.837..9.804 rows=104 loops=1) 
          Hash Cond: (foxtrot.xray_hotel = delta_yankee2.xray_hotel) 
          -> Nested Loop (cost=0.000..877.200 rows=104 width=340) (actual time=7.573..9.156 rows=104 loops=1) 
           -> Seq Scan on four_india foxtrot (cost=0.000..7.040 rows=104 width=216) (actual time=0.081..0.311 rows=104 loops=1) 
           -> Index Scan using three_delta on oscar alpha_victor (cost=0.000..8.350 rows=1 width=128) (actual time=0.077..0.078 rows=1 loops=104) 
             Index Cond: (quebec_seven2.lima = foxtrot.tango_three) 
          -> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.216..0.216 rows=34 loops=1) 
           -> Seq Scan on alpha_kilo quebec_foxtrot (cost=0.000..4.340 rows=34 width=30) (actual time=0.035..0.153 rows=34 loops=1) 
       -> Subquery Scan "*SELECT* 3" (cost=4.760..457.770 rows=5778 width=141) (actual time=0.264..58.353 rows=5777 loops=1) 
        -> Hash Join (cost=4.760..399.990 rows=5778 width=141) (actual time=0.253..39.062 rows=5777 loops=1) 
          Hash Cond: (four_uniform.xray_hotel = delta_yankee3.xray_hotel) 
          -> Seq Scan on whiskey four_uniform (cost=0.000..315.780 rows=5778 width=115) (actual time=0.112..15.759 rows=5778 loops=1) 
          -> Hash (cost=4.340..4.340 rows=34 width=30) (actual time=0.117..0.117 rows=34 loops=1) 
           -> Seq Scan on alpha_kilo golf (cost=0.000..4.340 rows=34 width=30) (actual time=0.005..0.059 rows=34 loops=1) 
     -> Hash (cost=2.430..2.430 rows=10 width=4) (actual time=0.303..0.303 rows=10 loops=1) 
       -> Subquery Scan "ANY_subquery" (cost=0.000..2.430 rows=10 width=4) (actual time=0.092..0.284 rows=10 loops=1) 
        -> Limit (cost=0.000..2.330 rows=10 width=68) (actual time=0.089..0.252 rows=10 loops=1) 
          -> Index Scan using tango_seven on zulu romeo (cost=0.000..257535.070 rows=1106504 width=68) (actual time=0.087..0.227 rows=10 loops=1) 
Total runtime: 24687.975 ms 
+1

आप हमें समझाएं चयन विश्लेषण दिखाया जा सका ...? शायद [depesz] (http://explain.depesz.com/) – MatheusOl

+0

का उपयोग करके मैं अस्थायी परिणामों को temp तालिका में डालने का प्रयास करूंगा, और IN (निष्पादन योग्य से आईडी का चयन करें) करूँगा। अंतर 'सीमा' खंड है जो अनुकूलक को तालिका 1 में प्रत्येक पंक्ति के लिए उप-चयन निष्पादित करने का कारण बन सकता है। पुनश्च यह प्रभावी रूप से @Clodoaldo के रूप में ही लगता है सुझाव दे रहा है – rootkit

+0

की कोशिश की 'somedata सीमा से aggregate_table आदेश से 10' का चयन के रूप में ext_id aggregate_table_tmp अस्थायी तालिका बनाने और उसके बाद सबक्वेरी में इसका उपयोग करने' table1 से चयन * जहां में आईडी (aggregate_table_tmp से ext_id चुनें) आदेश somedata द्वारा - कोई भाग्य नहीं। वही 25000ms। – Snifff

उत्तर

29

लगता है कि मैं अंत में एक समाधान पाया है:

select * 
    from view1 
    where view1.id = ANY(
         (select array(select ext_id 
            from aggregate_table 
            order by somedata limit 10) 
         )::integer[] 
        ) 
    order by view1.somedata; 

व्याख्या @ Dukeling के विचार के बाद:

मुझे लगता है जहां में आईडी (1, 2,3,4,5,6,7,8,9,10) अनुकूलित किया जा सकता है और में (का चयन करें ...) आईडी नहीं, कारण यह है किजा रहा है सकते हैं, जहां जबकि चुनिंदा नहीं है 0 (1,2,3,4,5,6,7,8,9,10), एक निरंतर अभिव्यक्ति है।

और तेजी से क्वेरी योजना

Recheck Cond: (id = ANY ('{1,2,3,4,5,6,7,8,9,10}'::integer[])) 
Index Cond: (id = ANY ('{1,2,3,4,5,6,7,8,9,10}'::integer[])) 

इस भी तेजी से काम करता है सवाल, 1.2ms के बारे में में पहली क्वेरी से इन लगाने, और अब यह

Recheck Cond: (id = ANY ($1)) 
Index Cond: (id = ANY ($1)) 

और बिटमैप स्कैन का उपयोग करता है योजना में

+11

'ARRAY' का उपयोग करना पीजी को सबक्वायरी में इंडेक्स का उपयोग करने के लिए निर्देश देना एक अच्छा चाल है। बीटीडब्ल्यू, उपर्युक्त 'किसी भी' खंड को 'किसी भी' सरणी (<आपकी चयन क्वेरी>)) ' –

+0

मेरे पास प्रयोग करने के लिए एक बड़ा डेटा (अभी तक) नहीं है, लेकिन @BlueSmith' array द्वारा सुझाए गए बजाय सरणी (चयन करें ...) का चयन करें (चुनें .. ।) '?' :: पूर्णांक [] 'कोई फर्क पड़ता है? उदाहरण के लिए, यदि मेरे पास स्ट्रिंग मान हैं, तो क्या मुझे तेज प्रदर्शन के लिए किसी भी प्रकार कास्ट करने की आवश्यकता है? – akostadinov

3

मैं where id in (1,2,3,4,5,6,7,8,9,10) अनुकूलित किया जा सकता है पर शक और where id in (select ...) नहीं कर सकते हैं, कारण

के रूप में अनुरोध

पहले क्वेरी का विश्लेषण व्याख्या यह (1,2,3,4,5,6,7,8,9,10) एक स्थिर ई है xpression, जबकि select नहीं है।

के बारे में कैसे:

WITH myCTE AS 
(
    SELECT ext_id 
    FROM aggregate_table 
    ORDER BY somedata 
    LIMIT 10 
) 
SELECT * 
FROM myCTE 
LEFT JOIN table1 
    ON myCTE.ext_id = table1.id 
ORDER BY somedata 
+0

एक ही रूप में @ Clodoaldo के संस्करण, 24000 एमएस – Snifff

+0

@Snifff' वाम JOIN' में बदला गया, एक फर्क कर सकते हैं। नीचे की रेखा यह प्रतीत होती है कि PostgreSQL अनुकूलन पर एक भयानक काम कर रहा है, मैं उसी डेटा पर MySQL या SQL सर्वर का प्रदर्शन देखना चाहता हूं। – Dukeling

+2

'बाएं जॉइन' में अंतर आता है - 65000ms तक का समय :( – Snifff