2012-10-03 9 views
5

मैं निम्न तालिका/अनुक्रमित है संयोजन Postgres -कई इंडेक्स

CREATE TABLE test 
(
    coords geography(Point,4326), 
    user_id varchar(50), 
    created_at timestamp 
); 
CREATE INDEX ix_coords ON test USING GIST (coords); 
CREATE INDEX ix_user_id ON test (user_id); 
CREATE INDEX ix_created_at ON test (created_at DESC); 

इस क्वेरी मैं निष्पादित करने के लिए चाहते हैं:

select * 
from updates 
where ST_DWithin(coords, ST_MakePoint(-126.4, 45.32)::geography, 30000) 
and user_id='3212312' 
order by created_at desc 
limit 60 

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

यह एक नई तालिका है जिसमें मैंने उत्पादन डेटा की थोक प्रविष्टि की है। test तालिका में कुल पंक्तियों: 15.069.489

मैं साथ (effective_cache_size = 2GB) PostgreSQL 9.2.1 चला रहा हूँ (PostGIS के साथ)। यह मेरा स्थानीय ओएसएक्स 16 जीबी रैम, कोर i7/2.5 गीगाहर्ट्ज, गैर-एसएसडी डिस्क है।

EXPLAIN ANALYZE उत्पादन जोड़ना -

Limit (cost=71.64..71.65 rows=1 width=280) (actual time=1278.652..1278.665 rows=60 loops=1) 
    -> Sort (cost=71.64..71.65 rows=1 width=280) (actual time=1278.651..1278.662 rows=60 loops=1) 
     Sort Key: created_at 
     Sort Method: top-N heapsort Memory: 33kB 
     -> Index Scan using ix_coords on test (cost=0.00..71.63 rows=1 width=280) (actual time=0.198..1278.227 rows=178 loops=1) 
       Index Cond: (coords && '0101000020E61000006666666666E63C40C3F5285C8F824440'::geography) 
       Filter: (((user_id)::text = '4f1092000b921a000100015c'::text) AND ('0101000020E61000006666666666E63C40C3F5285C8F824440'::geography && _st_expand(coords, 30000::double precision)) AND _st_dwithin(coords, '0101000020E61000006666666666E63C40C3F5285C8F824440'::geography, 30000::double precision, true)) 
       Rows Removed by Filter: 3122459 
Total runtime: 1278.701 ms 

अद्यतन:

नीचे दिए गए सुझावों मैं तार पर सूचकांक के आधार पर करने की कोशिश की + user_id:

CREATE INDEX ix_coords_and_user_id ON updates USING GIST (coords, user_id); 

..लेकिन निम्न त्रुटि मिलती है:

ERROR: data type character varying has no default operator class for access method "gist" 
HINT: You must specify an operator class for the index or define a default operator class for the data type. 

अद्यतन:

तो CREATE EXTENSION btree_gist; ने btree/gist compound अनुक्रमणिका समस्या हल की। और अब मेरी अनुक्रमणिका

CREATE INDEX ix_coords_user_id_created_at ON test USING GIST (coords, user_id, created_at); 

नोट: btree_gist डीईएससी/एएससी स्वीकार नहीं करता है।

नई क्वेरी योजना:

Limit (cost=134.99..135.00 rows=1 width=280) (actual time=273.282..273.292 rows=60 loops=1) 
    -> Sort (cost=134.99..135.00 rows=1 width=280) (actual time=273.281..273.285 rows=60 loops=1) 
     Sort Key: created_at 
     Sort Method: quicksort Memory: 41kB 
     -> Index Scan using ix_updates_coords_user_id_created_at on updates (cost=0.00..134.98 rows=1 width=280) (actual time=0.406..273.110 rows=115 loops=1) 
       Index Cond: ((coords && '0101000020E61000006666666666E63C40C3F5285C8F824440'::geography) AND ((user_id)::text = '4e952bb5b9a77200010019ad'::text)) 
       Filter: (('0101000020E61000006666666666E63C40C3F5285C8F824440'::geography && _st_expand(coords, 30000::double precision)) AND _st_dwithin(coords, '0101000020E61000006666666666E63C40C3F5285C8F824440'::geography, 30000::double precision, true)) 
       Rows Removed by Filter: 1 
Total runtime: 273.331 ms 

क्वेरी से पहले की तुलना में बेहतर प्रदर्शन कर रहा है, लगभग एक दूसरे बेहतर है लेकिन अभी भी महान नहीं। मुझे लगता है कि यह सबसे अच्छा है जो मैं प्राप्त कर सकता हूं ?? मैं लगभग 60-80ms के आसपास उम्मीद कर रहा था। क्वेरी से order by created_at desc भी लेते हुए, एक और 100ms बंद करता है, जिसका अर्थ है कि यह अनुक्रमणिका का उपयोग करने में असमर्थ है। इसे ठीक करने का कोई उपाय?

+0

पोस्टग्रेर्स एक लागत आधारित योजनाकार का उपयोग करता है। यहां तक ​​कि अगर यह इंडेक्स का उपयोग कर सकता है, तो यह उतना तेज़ नहीं हो सकता जितना इसका उपयोग नहीं कर रहा है। आप random_page_cost और cpu * cost vars के साथ यह देखने के लिए खेल सकते हैं कि आप इसे उन इंडेक्स का उपयोग करने में बात कर सकते हैं या नहीं। का विश्लेषण करने के लिए व्याख्या करें का उपयोग करें यह देखने के लिए कि यह क्या करने का निर्णय लेता है और यह कितना तेज़ है। –

+0

एक सूचकांक का उपयोग भी उपलब्ध आंकड़ों पर निर्भर करता है। वास्तव में कितनी पंक्तियों में 'user_id = '3212312'' है? क्या आपने इस क्वेरी से पहले 'वैक्यूम विश्लेषण' किया है (कम से कम तालिका को पॉप्युलेट करने के बाद)? – wildplasser

+0

यह देखने के लिए कि यह क्या करता है जब 'ix_coords' अनुक्रमणिका उपलब्ध नहीं है - चाहे वह अन्य अनुक्रमणिका का उपयोग कर सके और लागत क्या है - 'BEGIN; ड्रॉप इंडेक्स ix_coords ontable पर; EXPLAIN विश्लेषण_query; ROLLBACK; '। –

उत्तर

5

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

एक प्रयोग आप कर सकते थे के रूप में:

CREATE EXTENSION btree_gist; 
CREATE INDEX ix_coords_and_user_id ON test USING GIST (coords, user_id); 

जो एक बड़ा सूचकांक में परिणाम की संभावना है, लेकिन उस क्वेरी को बढ़ावा देने सकता है - अगर यह काम करता है। ध्यान रखें कि ऐसी इंडेक्स को बनाए रखने से INSERT और UPDATE एस धीमा हो जाएगा। आप पुराने ix_coords छोड़ अगर आपके प्रश्नों ix_coords_and_user_id का उपयोग करेगा, भले ही वे user_id पर फिल्टर नहीं है, लेकिन यह ix_coords की तुलना में धीमी हो जाएगा। दोनों को रखने से INSERT और UPDATE मंदी भी बदतर हो जाएगी।

:

btree-gist


(जब लिखा उपयोगकर्ता एक multicolumn सूचकांक वे अब दो अलग-अलग में विभाजित कर दिया है था संपादित करें द्वारा अप्रयुक्त है कि पूरी तरह से प्रश्न में परिवर्तन पर सवाल उठाने) देखें आप user_id पर फ़िल्टरिंग या सॉर्टिंग प्रतीत नहीं कर रहे हैं, केवल create_date। पीजी नहीं होगा (नहीं कर सकता?) मल्टी-कॉलम इंडेक्स की दूसरी अवधि का उपयोग करें जैसे (user_id, create_date), इसे पहले आइटम का भी उपयोग करने की आवश्यकता है।

यदि आप create_date को इंडेक्स करना चाहते हैं, तो इसके लिए एक अलग अनुक्रमणिका बनाएं। यदि आप (user_id, create_date) अनुक्रमणिका का उपयोग करते हैं और इसकी आवश्यकता है और आमतौर पर केवल user_id का उपयोग नहीं करते हैं, तो देखें कि आप कॉलम ऑर्डर को उलट सकते हैं या नहीं। वैकल्पिक रूप से दो स्वतंत्र इंडेक्स, (user_id) और (create_date) बनाएं। जब दोनों कॉलम की आवश्यकता होती है तो पीजी बिटमैप इंडेक्स स्कैन का उपयोग करके दो अपरिपक्व इंडेक्स को जोड़ सकता है।

+0

क्षमा करें मेरे पास मेरे प्रश्न में कुछ टाइपो थे, मिश्रित आईडी और user_id था, मूल रूप से यह सिर्फ "user_id" था। – kapso

+0

मैंने विश्लेषण विश्लेषण समझाया है। आपकी सहायता की सराहना। – kapso

+0

@ user310525 आपने 'ix_created_at' के' user_id' घटक को एक नई अनुक्रमणिका में विभाजित करके अपनी अनुक्रमणिका परिभाषाओं को पूरी तरह बदल दिया है। क्या पुराना सिर्फ गलत था? या आपने अपना सेटअप बदल दिया है और समझाया नहीं है? यदि आप इसे बदलते हैं, तो नई सामग्री को समझाने और जोड़ने के लिए बेहतर, न केवल चुपचाप बदलें कि पुराने क्या जवाब अब संदर्भ में समझ में नहीं आते हैं। –

2

मुझे लगता है कि क्रेग अपने जवाब के साथ सही है, लेकिन मैं बस कुछ चीजें जोड़ना चाहते थे (और यह एक टिप्पणी में फिट नहीं होगा)

आप बल PostgreSQL के लिए बहुत कड़ी मेहनत करनी उपयोग करने के लिए एक अनुक्रमणिका। क्वेरी ऑप्टिमाइज़र स्मार्ट है और ऐसे समय होते हैं जहां यह विश्वास करेगा कि अनुक्रमिक तालिका स्कैन तेज़ होगा। यह आमतौर पर सही है! :) लेकिन, आप कुछ सेटिंग्स (जैसे seq_page_cost, random_page_cost, आदि) के साथ खेल सकते हैं, आप इसे इंडेक्स के पक्ष में लाने और इसे प्राप्त करने के लिए खेल सकते हैं। यहां configurations में से कुछ का लिंक दिया गया है, जो आप जांचना चाहें कि क्या आपको लगता है कि यह सही निर्णय नहीं ले रहा है। लेकिन, फिर से ... मेरा अनुभव यह है कि ज्यादातर समय, पोस्टग्रेस मुझसे ज्यादा चालाक है! :)

आशा है कि इससे आपको (या भविष्य में कोई) मदद मिलेगी।

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