2012-11-24 13 views
5

मुझे runnerId के लिए सबसे कम मूल्य की आवश्यकता है।पोस्टग्रेस न्यूनतम फ़ंक्शन प्रदर्शन

इस क्वेरी:

SELECT "runnerId" FROM betlog WHERE "marketId" = '107416794' ; 

80 एमएस (1968 परिणाम पंक्तियां) लेता है।

यह:

SELECT min("runnerId") FROM betlog WHERE "marketId" = '107416794' ; 

1600 एमएस लेता है।

क्या न्यूनतम खोजने के लिए कोई तेज़ तरीका है, या क्या मुझे अपने जावा प्रोग्राम में न्यूनतम कैल्क करना चाहिए?

"Result (cost=100.88..100.89 rows=1 width=0)" 
" InitPlan 1 (returns $0)" 
" -> Limit (cost=0.00..100.88 rows=1 width=9)" 
"   -> Index Scan using runneridindex on betlog (cost=0.00..410066.33 rows=4065 width=9)" 
"    Index Cond: ("runnerId" IS NOT NULL)" 
"    Filter: ("marketId" = 107416794::bigint)" 

CREATE INDEX marketidindex 
    ON betlog 
    USING btree 
    ("marketId" COLLATE pg_catalog."default"); 

एक और विचार:

SELECT "runnerId" FROM betlog WHERE "marketId" = '107416794' ORDER BY "runnerId" LIMIT 1 >1600ms 
SELECT "runnerId" FROM betlog WHERE "marketId" = '107416794' ORDER BY "runnerId" >>100ms 

कैसे एक LIMIT नीचे क्वेरी धीमा कर सकते हैं?

+0

क्या आपके पास मार्केट पर इंडेक्स है? –

+1

[यह निष्कर्ष निकालने के लिए कि क्यों एक कथन निष्पादित करने में इतना समय लग रहा है EXPLAIN कमांड के साथ किया जाता है] (http://wiki.postgresql.org/wiki/Using_EXPLAIN) – raina77ow

+0

हां इसमें इंडेक्स – wutzebaer

उत्तर

8

आप क्या जरूरत है एक multi-column index है:

CREATE INDEX betlog_mult_idx ON betlog ("marketId", "runnerId"); 

रुचि रखते हैं, तो आप PostgreSQL में बहु-स्तंभ अनुक्रमणिका के बारे में गहराई से जानकारी मिल जाएगा, this related question on dba.SE के तहत लिंक और मानक।

मुझे कैसे पता चला?
बहु-स्तंभ सूचकांक में, सूचकांक ("बाजार आईडी") के पहले कॉलम द्वारा पंक्तियों का आदेश दिया जाता है (और इस प्रकार क्लस्टर्ड), और प्रत्येक क्लस्टर को सूचकांक के दूसरे कॉलम द्वारा क्रमशः आदेश दिया जाता है - इसलिए पहली पंक्ति min("runnerId") की स्थिति से मेल खाता है। यह इंडेक्स स्कैन बेहद तेज़ बनाता है।

LIMIT के विरोधाभासी प्रभाव के बारे में एक प्रश्न धीमा करना - पोस्टग्रेस क्वेरी प्लानर की कमजोरी है। सामान्य कार्यवाही इस मामले में एक सीटीई ( आवश्यक नहीं है) का उपयोग करना है। इस हाल, निकट से संबंधित प्रश्न के अंतर्गत अधिक जानकारी प्राप्त करें:
PostgreSQL query taking too long

+0

वाह इस समस्या को हल किया, क्या आप थोड़ा सा पृष्ठभूमि दे सकते हैं क्यों? आप इसे कैसे पहचानते थे? – wutzebaer

+1

@wutzebaer: मैंने मैन्युअल के लिए एक लिंक जोड़ा, एक प्रश्न का एक लिंक जिसमें बहु-स्तंभ अनुक्रमणिका और कुछ स्पष्टीकरण के बारे में अधिक जानकारी है। –

+0

यह वास्तव में अजीब है - "खराब" क्वेरी से क्या समझाया जाता है? प्रसंस्करण 4065 पंक्तियों में 1500 मीटर नहीं लगना चाहिए। –

1

न्यूनतम विवरण पूरे तालिका के अनुक्रमिक स्कैन का उपयोग करके PostgreSQL द्वारा निष्पादित किया जाएगा। आप निम्न दृष्टिकोण का उपयोग कर क्वेरी को अनुकूलित कर सकते हैं: कॉल ASC LIMIT 1 द्वारा कुछ आदेशों से चयन करें;

+0

है जो बस इष्ट तेजी से ऑर्डर कर रहा है >> चुनें "runnerId" betlog से "marketId" = '107416794' "runnerId" द्वारा आदेश << लेकिन जब मैं "LIMIT 1" जोड़ता हूं तो यह 1600 एमएस पर फिर से – wutzebaer

+0

पर मूल रूप से आप सीमा कथन के बिना दृष्टिकोण का उपयोग कर सकते हैं। यह आपकी तरफ से क्वेरी को अनुकूलित करना चाहिए। –

+0

ठीक है, लेकिन एक सीमा क्वेरी को धीमा कैसे कर सकती है? यह एक समस्या है क्योंकि मैं इस क्वेरी का उपयोग subquery – wutzebaer

1

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

यह भी पूरे टेबल को स्कैन करने और पंक्तियों से मिलान करने के साथ-साथ संभवतः कई अन्य विकल्पों को चुनने की लागत का अनुमान लगाता है। यह हमेशा एक निश्चित प्रकार की योजना का उपयोग नहीं करता है, लेकिन सभी विकल्पों की लागत की तुलना करता है।

समस्या यह है कि यह मानना ​​है कि मानों को यादृच्छिक रूप से श्रेणी में वितरित किया जाना आवश्यक नहीं है (जैसा कि इस उदाहरण में), अंत में छिपी हुई पंक्तियों को खोजने के लिए सीमा के उच्च प्रतिशत का स्कैन होता है। "marketId" के कुछ मानों के लिए, जहां चुना गया मान "runnerId" अनुक्रमणिका की शुरुआत के निकट उपलब्ध है, यह योजना बहुत तेज होनी चाहिए।

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

असल में यह एक और आकर्षक योजना उपलब्ध कराने या अनुकूलन बाधा पेश करने के लिए नीचे आता है। इस मामले में आप ("marketId", "runnerId") पर इंडेक्स जोड़ कर एक और अधिक आकर्षक विकल्प प्रदान कर सकते हैं - जो सीधे उत्तर पर जाने का एक सीधा तरीका प्रदान करता है। योजनाकार उस विकल्प के लिए बहुत कम लागत निर्दिष्ट करता है, जिससे इसे चुना जा सकता है।

SELECT min("runnerId") 
    FROM (SELECT "runnerId" FROM betlog 
      WHERE "marketId" = '107416794' 
      OFFSET 0) x; 

जब एक OFFSET धारा नहीं है (यहां तक ​​कि एक शून्य की भरपाई के लिए) यह सबक्वेरी अलग से योजना बनाई होने के लिए बाध्य: आप सूचकांक को जोड़ने के लिए नहीं पसंद करते हैं, तो आप एक अनुकूलन बाधा कुछ इस तरह करने से मजबूर कर सकता है और इसके परिणाम बाहरी क्वेरी को खिलाया गया। मैं उम्मीद करता हूं कि इसे ऑप्टिमाइज़ेशन बाधा के बिना प्राप्त होने वाले 1600 एमएस के बजाय 80 एमएस में चलाने की उम्मीद है। बेशक, यदि आप इंडेक्स जोड़ सकते हैं, तो डेटा कैश किए जाने पर क्वेरी की गति 1 एमएस से कम होनी चाहिए।

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