स्थानिक कार्य के माध्यम से पंक्तियाँ सीमित करें


9

मैं नीचे क्वेरी के लिए प्रदर्शन में सुधार करने की कोशिश कर रहा हूं। इससे कोई फर्क नहीं पड़ता कि मैं क्वेरी कैसे लिखता हूं (FROM क्लॉज में उपखंड, WHERE क्लॉज में सबक्वेरी) सब ~ 570K पंक्तियों को महंगे ST_DWITHIN फ़ंक्शन के माध्यम से चलाने पर जोर देता है, भले ही काउंटी # 24 पर केवल 60 पंक्तियां हों। मैं काउंटी पर फ़िल्टर करने के लिए पोस्टग्रेज़ कैसे प्राप्त कर सकता हूं = 24 बीफ़ोर पोस्टगिस फंक के माध्यम से चल रहा है जो मुझे लगता है कि बहुत तेज और कहीं अधिक कुशल होगा? 700ms बहुत अधिक चिंता का कारण नहीं है, लेकिन जैसे ही यह तालिका 10M + बढ़ जाती है, मैं प्रदर्शन के बारे में चिंतित हूं।

नोट करने के लिए, p.id एक प्राथमिक कुंजी है, p.zipcode एक fk इंडेक्स है, z.county एक fk इंडेक्स है, और p.geom में GiST इंडेक्स है।

प्रश्न:

EXPLAIN ANALYZE
  SELECT count(p.id)
  FROM point AS p
  LEFT JOIN zipcode AS z
    ON p.zipcode = z.zipcode
  WHERE z.county = 24
    AND ST_DWithin(
      p.geom, 
      ST_SetSRID(ST_Point(-121.479756008715,38.563236291512),4269), 
      16090.0,
      false
    )

चुनौती का पालन करें:

Aggregate  (cost=250851.91..250851.92 rows=1 width=4) (actual time=724.007..724.007 rows=1 loops=1)
  ->  Hash Join  (cost=152.05..250851.34 rows=228 width=4) (actual time=0.359..723.996 rows=51 loops=1)
        Hash Cond: ((p.zipcode)::text = (z.zipcode)::text)
        ->  Seq Scan on point p  (cost=0.00..250669.12 rows=7437 width=10) (actual time=0.258..723.867 rows=63 loops=1)
              Filter: (((geom)::geography && '0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography) AND ('0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography && _st_expand((geom)::geography, 16090::double precision)) AND _st_dwithin((g (...)
              Rows Removed by Filter: 557731
        ->  Hash  (cost=151.38..151.38 rows=54 width=6) (actual time=0.095..0.095 rows=54 loops=1)
              Buckets: 1024  Batches: 1  Memory Usage: 3kB
              ->  Bitmap Heap Scan on zipcode z  (cost=4.70..151.38 rows=54 width=6) (actual time=0.023..0.079 rows=54 loops=1)
                    Recheck Cond: (county = 24)
                    Heap Blocks: exact=39
                    ->  Bitmap Index Scan on fki_zipcode_county_foreign_key  (cost=0.00..4.68 rows=54 width=0) (actual time=0.016..0.016 rows=54 loops=1)
                          Index Cond: (county = 24)
Planning time: 0.504 ms
Execution time: 724.064 ms

हो सकता है कि लाइन को बदलने की कोशिश करें "पी के रूप में पी लेफ्ट ज्वाइन ज्वाइंट के रूप में जेड" कुछ इस तरह से "पी लेफ्ट ज्वाइन (सिलेक्ट * फ्रॉम जिपकोड जहां जिपकोड.नौटी = 24) जेड के रूप में"?
वीजी १४

बस कोशिश की, वही परिणाम। जब मैं ~ 60 pointपंक्तियों को कॉपी करता हूं, जहां काउंटी = 24 एक नई तालिका में सभी अपने आप से, क्वेरी 745 की तुलना में केवल .453ms लेती है तो निश्चित रूप से एक बड़ा अंतर है।
जोश

1
आपको count(*)स्टाइल के मामले के रूप में उपयोग करना चाहिए । यदि idआप कहते हैं कि एक पीकेडी है, तो NOT NULLइसका मतलब है कि वे समान हैं। सिवाय count(id)इसकी खामी है कि आपको यह सवाल पूछना है कि क्या idयह अशक्त है।
इवान कैरोल

1
क्या मैं पूछ सकता हूं कि आप एक बाहरी बाहरी जुड़ाव का उपयोग क्यों कर रहे हैं? इसे एक आंतरिक जोड़ में बदलने का प्रयास करें ... परिणाम समान होना चाहिए
मिकी

यदि z.country सीमित कारक है, तो मेरा सुझाव है कि आप इसे पहले CTE क्वेरी में डाल दें और फिर अपनी रुचि के साथ चौराहे के लिए उन परिणामों की जांच करें। जैसा कि स्थानिक सूचकांक शायद इस मामले में काउंटी = 24 की तुलना में कम चयनात्मक है, यह केवल रास्ते में हो रहा है।
जॉन पॉवेल

जवाबों:


3

आप समस्या को वास्तविक बनाम वास्तविक गणना के साथ देख सकते हैं। योजनाकार सोचता है कि 7,437 पंक्तियाँ हैं, हालांकि केवल 63 हैं। आँकड़े बंद हैं। दिलचस्प रूप से पर्याप्त भी, यह एक बाउंडिंग बॉक्स इंडेक्स (सूचकांक) खोज का उपयोग नहीं कर रहा है जिसके साथ DWithinआप इसका परिणाम पेस्ट कर सकते हैं \d point। PostGIS और PostgreSQL का क्या संस्करण?

दौड़ने की कोशिश करो ANALYZE point। जब आप हालत को ऊपर ले जाते हैं तो क्या आपको वही योजना मिलती है?

JOIN zipcode AS z
  ON p.zipcode = z.zipcode
  AND z.county = 24

मैंने विश्लेषण चलाया और ऑन में नई और शर्त की भी कोशिश की, लेकिन अभी भी 700ms रन बार हो रहा था। यह PGSQL 9.4 और PostGIS 2.2 है।
जोश

2

एक साइड नोट के रूप में, एक उचित मौका है कि यदि आप इसे बग कहना चाहते हैं तो यह व्यवहार PostGIS 2.3.0 में संशोधित है।

PostgreSQL पर डॉक्स से

Cpu_operator_cost की इकाइयों में फ़ंक्शन के लिए अनुमानित निष्पादन लागत देने वाली एक सकारात्मक संख्या। यदि फ़ंक्शन एक सेट लौटाता है, तो यह प्रति पंक्ति की लागत है। यदि लागत निर्दिष्ट नहीं है, तो सी-भाषा और आंतरिक कार्यों के लिए 1 इकाई, और अन्य सभी भाषाओं में कार्यों के लिए 100 इकाइयाँ मान ली गई हैं। बड़े मान योजनाकार को कारण की तुलना में अधिक बार फ़ंक्शन का मूल्यांकन करने से बचने की कोशिश करते हैं।

तो डिफ़ॉल्ट लागत 1 (बहुत सस्ती) थी। D_WithinGIST इंडेक्स का उपयोग करना बहुत सस्ता है। लेकिन, इसे बढ़ाकर 100 कर दिया गया (आंतरिक के प्रॉक्सी से _ST_DWithin)।

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


1

जॉन पॉवेल के संकेत की बदौलत मैंने काउंटी को सीमित करने की शर्त को CTE / CTE प्रश्न के साथ संशोधित किया और इस प्रदर्शन में काफी सुधार हुआ और यह 222ms बनाम 700 हो गया। फिर भी .74 एमएस से बहुत दूर रोता है जब डेटा इसके अंदर होता है। खुद की मेज। मुझे अभी भी यकीन नहीं है कि प्लानर एक महंगी पोस्टगिस फ़ंक्शन के माध्यम से चलने से पहले डेटा सेट को सीमित क्यों नहीं करता है, और मुझे बड़े डेटासेट के साथ प्रयास करना होगा जब मेरे पास होगा लेकिन यह अब के लिए इस अनूठी स्थिति का समाधान प्रतीत होता है।

with points as (
   select p.id, p.geom from point p inner join zipcode z
   on p.zipcode = z.zipcode
   where county = 24
   ) 


SELECT count(points.id)
FROM points
WHERE ST_DWITHIN(points.geom, (ST_SetSRID(ST_Point(-121.479756008715,38.563236291512),4269)), 16090.0, false)

1
हमें सभी तीन क्वेरी प्लान और तालिका के लिए स्कीमा (मेरे उत्तर \ _ बिंदु में अनुरोधित) को देखना होगा।
इवान कैरोल

0

आपको एक इंडेक्स बनाना चाहिए zipcode(county, zipcode), जिससे आपको एक इंडेक्स केवल z पर स्कैन करना चाहिए।

तुम भी साथ प्रयोग करने के लिए कर सकते हैं btree_gistया तो बनाने विस्तार point(zipcode, geom)सूचकांक या point(geom, zipcode)और zipcode(zipcode, county)सूचकांक।

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