2011-11-01 14 views
5

मेरे पास एक कॉलम tmp_drop_ids एक कॉलम, id और 3.3 मिलियन प्रविष्टियों के साथ एक तालिका है। मैं टेबल पर फिर से शुरू करना चाहता हूं, हर 200 प्रविष्टियों के साथ कुछ कर रहा हूं। मैं इस कोड है:postgresql: ऑफसेट + सीमा बहुत धीमी हो जाती है

LIMIT = 200 
for offset in xrange(0, drop_count+LIMIT, LIMIT): 
    print "Making tmp table with ids %s to %s/%s" % (offset, offset+LIMIT, drop_count) 
    query = """DROP TABLE IF EXISTS tmp_cur_drop_ids; CREATE TABLE tmp_cur_drop_ids AS 
    SELECT id FROM tmp_drop_ids ORDER BY id OFFSET %s LIMIT %s;""" % (offset, LIMIT) 
    cursor.execute(query) 

यह पहली बार में ठीक, चलाता है, (~ 0.15s tmp तालिका उत्पन्न करने के लिए), लेकिन यह कभी कभी जैसे धीमी हो जाएगी, लगभग 300k टिकटों ने इस टीएमपी टेबल को उत्पन्न करने के लिए 11-12 सेकेंड लगाना शुरू किया, और फिर लगभग 400k। यह मूल रूप से अविश्वसनीय लगता है।

मैं उन प्रश्नों का उपयोग अन्य प्रश्नों में करूँगा, इसलिए मुझे एक टीएमपी टेबल में रखने के लिए सबसे अच्छी जगह मिली। क्या इस तरह के परिणामों के माध्यम से पुन: प्रयास करने का कोई बेहतर तरीका है?

+0

क्या आपके पास tmp_drop_ids अनुक्रमित है? अद्वितीय INDEX tmp_drop_ids_id_uidx बनाएं tmp_drop_ids (आईडी) पर; – filiprem

+0

@ फ़िलिप्रम: मैं हाँ – Claudiu

उत्तर

9

इसके बजाए एक कर्सर का उपयोग करें। ऑफ़सेट और LIMIT का उपयोग करना बहुत महंगा है - क्योंकि पीजी को क्वेरी निष्पादित करना, प्रक्रिया करना और ऑफसेट पंक्तियों को छोड़ना है। ऑफसेट "पंक्तियों को छोड़ना" जैसा है, जो महंगा है।

cursor documentation

कर्सर एक क्वेरी के ऊपर एक यात्रा की अनुमति देता है।

BEGIN 
DECLARE C CURSOR FOR SELECT * FROM big_table; 
FETCH 300 FROM C; -- get 300 rows 
FETCH 300 FROM C; -- get 300 rows 
... 
COMMIT; 

शायद आप एक सर्वर साइड कर्सर की घोषणा बयान के स्पष्ट का उपयोग किए बिना, बस psycopg (सर्वर साइड कर्सर के बारे में खोज अनुभाग) में समर्थन के साथ उपयोग कर सकते हैं।

+0

करता हूं, मैंने इसे पायथन से कर लिया (कर्सर ऑब्जेक्ट की 'fetchmany' का उपयोग करके)। – Claudiu

2

अपने आईडी के इंडेक्स रहे हैं, तो आप ">" के साथ "सीमा" का उपयोग कर सकते, अजगर की तरह स्यूडोकोड में उदाहरण के लिए:

limit=200 
max_processed_id=-1 
query ("create table tmp_cur_drop_ids(id int)") 
while true: 
    query("truncate tmp_cur_drop_ids") 
    query("insert into tmp_cur_drop_ids(id)" \ 
     + " select id from tmp_drop_ids" \ 
     + " where id>%d order by id limit %d" % (max_processed_id, limit)) 
    max_processed_id = query("select max(id) from tmp_cur_drop_ids") 
    if max_processed_id == None: 
    break 
    process_tmp_cur_drop_ids(); 
query("drop table tmp_cur_drop_ids") 

इस तरह Postgres आपकी क्वेरी के लिए सूचकांक का उपयोग कर सकते हैं।

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