2011-06-07 15 views
6

पर कुशल डेटा माइग्रेशन मुझे बड़ी (5 मीटर पंक्ति) django तालिका में एक नया कॉलम जोड़ने की आवश्यकता है। मेरे पास दक्षिण schemamigration है जो नया कॉलम बनाता है। अब मैं नए कॉलम को पॉप्युलेट करने के लिए datamigration स्क्रिप्ट लिख रहा हूं। यह इस तरह दिख रहा है। (आप दक्षिण माइग्रेशन से परिचित नहीं हैं, तो बस की अनदेखी orm. मॉडल का नाम लगाकर।)एक बड़ी django तालिका

print "Migrating %s articles." % orm.Article.objects.count() 
cnt = 0 
for article in orm.Article.objects.iterator():    
    if cnt % 500 == 0: 
     print " %s done so far" % cnt 
    # article.newfield = calculate_newfield(article) 
    article.save() 
    cnt += 1 

मैं objects.iterator को objects.all से बदल स्मृति आवश्यकताओं को कम। लेकिन जब भी मैं इस स्क्रिप्ट को चलाता हूं तब भी कुछ यादगार स्मृति को चबा रहा है। यहां तक ​​कि वास्तव में उपयोगी लाइन के ऊपर भी टिप्पणी की गई है, फिर भी स्क्रिप्ट अभी भी टेबल के माध्यम से बहुत दूर होने से पहले 10+ जीबी रैम का उपयोग करने के लिए बढ़ती है और मैं इसे छोड़ देता हूं।

ऐसा लगता है कि स्मृति में इन वस्तुओं को कुछ पकड़ रहा है। मैं इसे कैसे चला सकता हूं इसलिए यह एक स्मृति हॉग नहीं है?

एफडब्ल्यूआईडब्ल्यू, मैं अजगर 2.6, डीजेंगो 1.2.1, दक्षिण 0.7.2, mysql 5.1 का उपयोग कर रहा हूं।

उत्तर

7

सुनिश्चित settings.DEBUGFalse को तैयार है। DEBUG=True विशेष रूप से डेटाबेस गहन संचालन के साथ स्मृति भरता है, क्योंकि यह आरडीबीएमएस को भेजे गए सभी प्रश्नों को एक दृश्य में संग्रहीत करता है।

Django 1.8 के साथ, यह आवश्यक नहीं होना चाहिए क्योंकि हार्ड ड्राइव पहले 9 000 प्रश्नों को पहले अनंत नंबर की बजाय संग्रहीत किया जाता है।

+0

इसे मेरे लिए हल करता है। मुझे लगता है कि DEBUG पूरी क्वेरी कैश करता है, इसलिए यदि आप अपने डेटा माइग्रेशन के हिस्से के रूप में 10 जीबी डाल रहे हैं, तो यह 10 जीबी मेमोरी का उपयोग करता है। या मेरे मामले में दुर्घटनाओं में, क्योंकि मैं 32-बिट पीएई कर्नेल का उपयोग कर रहा हूं। –

+0

क्या यह ट्विक अभी भी Django के नए संस्करणों में आवश्यक है? – nivniv

+0

यह Django 1.7 तक आवश्यक है, लेकिन अभी भी अनुशंसित है: स्मृति में संग्रहीत 9 000 प्रश्नों की हार्ड सीमा Django 1.7 या 1.8 में स्थापित की गई है। –

2

Django के ORM में आपका स्वागत है। मुझे लगता है कि यह एक अंतर्निहित समस्या है।

मुझे बड़े डेटाबेस, डंपडाटा, लोडडाटा और इसी तरह की समस्याएं भी हैं।

आपके पास दो विकल्प हैं।

  1. दक्षिण का उपयोग करने की कोशिश करना बंद करें और अपना स्वयं का ओआरएम माइग्रेशन लिखें। आपकी सेटिंग्स में आपके पास एकाधिक डेटाबेस परिभाषाएं हो सकती हैं। "पुराना" और "नया" बनाएं। पुराने डेटाबेस से नए डेटाबेस में अपना एक बार माइग्रेटर लिखें। एक बार यह परीक्षण और काम करने के बाद, इसे एक अंतिम बार चलाएं और फिर डेटाबेस परिभाषाओं को स्विच करें और Django को पुनरारंभ करें।

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

यह दक्षिण या ओआरएम विशेष रूप से खराब नहीं है। लेकिन, बड़े डेटाबेस में थोक प्रसंस्करण के लिए, वे स्मृति में बहुत ज्यादा कैश करते हैं।

1

यदि आपको ऑब्जेक्ट्स तक पूर्ण पहुंच की आवश्यकता नहीं है, तो आप हमेशा अपनी क्वेरीसेट पर only और values या values_list का कॉम्बो का उपयोग कर सकते हैं। इससे मेमोरी आवश्यकताओं को काफी कम करने में मदद मिलनी चाहिए, लेकिन मुझे यकीन नहीं है कि यह पर्याप्त होगा या नहीं।

2

orm.Article.objects.iterator()

कि पूरे क्वेरी चलाने और स्मृति में परिणाम को बचाने करता है? या एक समय में डेटाबेस से पंक्तियां लाएं?

मुझे लगता है कि यह सब एक बार में यह अनुमान लगा रहा है।

जैसे:: http://docs.python.org/library/sqlite3.html#sqlite3.Cursor.fetchmany

db = blah.connect("host='%s' dbname='%s' user='%s' password='%s'" % ... 
new, old = db.cursor(), db.cursor() 
old.execute(""" 
    SELECT * 
    FROM whatever 
""") 
for row in old.fetchmany(size=500): 
    (col1, col2, col3...) = row 
    new = db.cursor() 
    new.execute(""" 
     INSERT INTO yourtable (
      col1, col2, col3...) 
     VALUES (
      %s, %s, %s, %s, %s) 
     """,(col1, col2, col3,...)) 
new.close() 
old.close() 

यह धीमी गति से हो सकता है अगर आप एक डेटाबेस कर्सर कि एक वृद्धिशील फैशन में डेटा खींचती साथ कि पाश की जगह ले सकता देखें। मैंने इसे मेरी एक स्टैंडअलोन माइग्रेशन स्क्रिप्ट से खींच लिया ताकि यमव।

fetchmany मानक (पीईपी 24 9) है।मैंने वही नहीं किया है जो आप खोज रहे हैं, इस नमूने से अभी भी थोड़ा काम करना है: मैंने लूप पर लूप नहीं किया है - 500 तक सेट करने के लिए - तो आपको इसे बाहर करने की आवश्यकता होगी स्वयं के लिए।

+0

क्या यह mysql के लिए भी काम करता है? – Leopd

+0

हां। fetchmany मानक है (पीईपी 24 9)। –

2

या, यदि आप सीटू में कच्ची क्वेरी बनाते हैं तो क्या होता है जो एक प्राथमिक परिणाम आकार सीमा लागू करता है?

एक ला: https://docs.djangoproject.com/en/1.3/topics/db/sql/#index-lookups

while min < rowcount: 
    min += 500 
    max = min + 500 
    articles = Article.objects.raw('SELECT * from article where id > %s and id < %s' % (min, max)) 
    for old_article in articles: 
    # create the new article 
    article.save() 
संबंधित मुद्दे