2013-04-15 7 views
5

अनुकूलित करना मेरे पास feeds_up नामक PostgreSQL डेटाबेस में एक तालिका है। ऐसा लगता है:सबसे हालिया रिकॉर्ड, तिथि से पहले, श्रेणी के अनुसार:

| feed_url | isup | hasproblems | observed timestamp with tz | id (pk)| 
|----------|------|-------------|-------------------------------|--------| 
| http://b.| t | f   | 2013-02-27 16:34:46.327401+11 | 15235 | 
| http://f.| f | t   | 2013-02-27 16:31:25.415126+11 | 15236 | 

इसमें 300k पंक्तियों की तरह कुछ है, जो हर पांच मिनट में ~ 20 पंक्तियों में बढ़ रहा है। मेरे पास एक क्वेरी है जो अक्सर चलती है (प्रत्येक पृष्ठ लोड)

select distinct on (feed_url) feed_url, isUp, hasProblems 
    from feeds_up 
    where observed <= '2013-02-27T05:38:00.000Z' 
    order by feed_url, observed desc; 

मैंने वहां एक उदाहरण दिया है, उस समय पैरामीट्रिज्ड है। व्याख्या विश्लेषण explain.depesz.com पर है। इसमें लगभग 8s लगता है। पागल!

feed_url के लिए केवल 20 अद्वितीय मान हैं, इसलिए यह वास्तव में अक्षम है। मैंने सोचा कि मैं बेवकूफ होगा और एक समारोह में फॉर लूप का प्रयास करूंगा।

CREATE OR REPLACE FUNCTION feedStatusAtDate(theTime timestamp with time zone) RETURNS SETOF feeds_up AS 
$BODY$ 
DECLARE 
    url feeds_list%rowtype; 
BEGIN 
FOR url IN SELECT * FROM feeds_list 
LOOP 
    RETURN QUERY SELECT * FROM feeds_up 
    WHERE observed <= theTime 
    AND feed_url = url.feed_url 
    ORDER BY observed DESC LIMIT 1; 
END LOOP; 
END; 
$BODY$ language plpgsql; 

select * from feedStatusAtDate('2013-02-27T05:38:00.000Z'); 

कि सिर्फ 307ms ले जाता है!

एसक्यूएल में एक फोर लूप का उपयोग करके मुझे गलत तरीके से रगड़ता है, मैं एक अच्छी क्वेरी कैसे बना सकता हूं-पहले की तरह-वह कुशल है? क्या यह संभव है? या यह ऐसी चीज है जहां फॉर लूप वास्तव में सबसे अच्छा है?

ईटीए

Postgres संस्करण: PostgreSQL 9.1.5 i686-पीसी-linux-gnu, (SUSE लाइनेक्स) 4.3.4 [जीसीसी-4_3 शाखा संशोधन 152,973] जीसीसी द्वारा संकलित पर, 32-बिट feeds_up पर

इंडेक्स:

CREATE INDEX feeds_up_url 
    ON feeds_up 
    USING btree 
    (feed_url COLLATE pg_catalog."default"); 

CREATE INDEX feeds_up_url_observed 
    ON feeds_up 
    USING btree 
    (feed_url COLLATE pg_catalog."default", observed DESC); 

CREATE INDEX feeds_up_observed 
    ON public.feeds_up 
    USING btree 
    (observed DESC); 
+0

बस एफवाईआई @ कैथी ने निम्नलिखित परिणाम के साथ 'work_mem' को 20MB तक अपनाने का प्रयास किया है: http://explain.depesz.com/s/UJw (उत्तर में टिप्पणियों से मैंने अब हटा दिया है)। सॉर्ट अब डिस्क पर नहीं फैलता है लेकिन क्वेरी काफी तेज़ नहीं है। इंडेक्स बनाना 'CREEX INDEX फ़ीड्स_अप_फेड_यूआरएल_ब्सवर्ड फीड_अप पर (फीड_यूआरएल, डीईएससी मनाया गया);' कोई अच्छा नहीं था; सूचकांक का उपयोग नहीं किया जाता है। –

+0

किस तरह से postgreSQL संस्करण, वैसे? 'चयन संस्करण()'। –

+0

@ क्रेग्रिंजर 9.1.5, मैं एक संपादन कर दूंगा। – Cathy

उत्तर

1

यह मानते हुए कि "आईडी" धारावाहिक और हमेशा अनुक्रमिक है, तो आप एक सबक्वेरी में प्रत्येक FEED_URL के लिए MAX (आईडी) का पता लगाकर को आसान बनाने में कर सकते हैं और फिर डेटा के बाकी हिस्सों में खींच इस प्रकार है:

SELECT fu.feed_url, fu.isup, fu.hasproblems, fu.observed 
FROM feeds_up fu 
JOIN 
(
    SELECT feed_url, max(id) AS id FROM feeds_up 
    WHERE observed <= '2013-03-27T05:38:00.000Z' 
    GROUP BY feed_url 
) AS q USING (id); 
ORDER BY fu.feed_url, fu.observed desc; 

मैंने एक त्वरित परीक्षण किया और यह "मनाए गए" पर केवल एक सूचकांक का उपयोग करके बहुत कुशलता से काम करता है।

अद्यतन:

उपयोग करने के लिए "मनाया" "आईडी" के बजाय (रिकॉर्ड के बाद से क्रम में सम्मिलित नहीं हो सकता है) के रूप में आप क्वेरी ऊपर संशोधित कर सकते हैं:

SELECT DISTINCT ON (fu.feed_url) fu.feed_url, fu.isup, fu.hasproblems, fu.observed 
FROM feeds_up fu 
JOIN 
(
    SELECT feed_url, max(observed) as observed FROM feeds_up 
    WHERE observed <= '2013-03-27T05:38:00.000Z' 
    GROUP BY feed_url 
) AS q USING (feed_url, observed) 
ORDER BY fu.feed_url, fu.observed desc; 

अपने सिस्टम इस में भाग गया पर "मनाया" पर एक सूचकांक के साथ लगभग उसी समय। वाईएमएमवी

+0

यही वही है जो मैं ढूंढ रहा था! एक गर्म कैश के साथ 100ms से कम। – Cathy

0

क्या आप का वर्णन करना चाहिए कि आप क्या indexs है अनुकूलित करने के बारे में बात कर रहे हैं।

मैं एक है कि "मनाया"

एक और सूचकांक होगा में पूरी तरह से अनिवार्य एक सूचकांक है "FEED_URL, मनाया"

अंत में "FEED_URL" में एक, उपयोगी हो सकता है लगता है, लेकिन मैं तो नहीं कर रहा हूँ सुनिश्चित करें कि यह अच्छा से ज्यादा गर्म होगा। बेशक इन सभी का नकारात्मक हिस्सा डालने पर प्रदर्शन होगा, लेकिन इसके लिए मुझे समस्या को थोड़ा बेहतर तरीके से जानना होगा।

क्या आपने "feed_url" द्वारा पर विचार किया है (क्योंकि आप कहते हैं कि आपके पास केवल कुछ सीमित हैं)? अन्यथा तिथि (महीने) द्वारा "मनाया"?

+0

मैंने इंडेक्स को जोड़ने के लिए संपादित किया है। जैसा कि @ क्रैग्रिंजर ऊपर बताता है, मैंने संयुक्त सूचकांक बनाने का प्रयास किया है, लेकिन क्वेरी प्लानर ने इसका उपयोग नहीं किया है (हां, मैं 'वैक्यूम विश्लेषण 'डी)। – Cathy

+0

मुझे नहीं लगता कि feed_url द्वारा एक विभाजन मदद करेगा, क्योंकि मैं हमेशा प्रत्येक में से एक ले रहा हूं (जब तक कि मैं विभाजन को गलत समझ नहीं पा रहा हूं?)। मैं "मनाया" द्वारा विभाजन का प्रयास करने के लिए तैयार हूं, (मुझे मौजूदा तालिका के लिए कोई निर्देश नहीं मिल रहा है?) हालांकि यह प्रति माह 200k पंक्तियों वाली तालिका के लिए थोड़ा चरम लगता है। – Cathy

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