2009-07-16 8 views
61

मुझे Django के ORM का उपयोग करके SQLite डेटाबेस में 8000+ रिकॉर्ड डालना होगा। इस ऑपरेशन को प्रति मिनट एक बार cronjob के रूप में चलाने की जरूरत है।
फिलहाल मैं सभी वस्तुओं के माध्यम से दोहराने के लिए लूप का उपयोग कर रहा हूं और फिर उन्हें एक-एक करके सम्मिलित कर रहा हूं।
उदाहरण:Django का उपयोग कर SQLite तालिका में हजारों रिकॉर्ड डालने का एक प्रभावी तरीका क्या है?

for item in items: 
    entry = Entry(a1=item.a1, a2=item.a2) 
    entry.save() 

ऐसा करने का एक कारगर तरीका क्या है?

संपादित करें: दो सम्मिलन विधियों के बीच एक छोटी तुलना।

commit_manually डेकोरेटर के बिना (11245 रिकॉर्ड):

[email protected] marinetraffic]$ time python manage.py insrec    

real 1m50.288s 
user 0m6.710s 
sys  0m23.445s 

commit_manually डेकोरेटर का उपयोग करना (11245 रिकॉर्ड):

[[email protected] marinetraffic]$ time python manage.py insrec     

real 0m18.464s 
user 0m5.433s 
sys  0m10.163s 

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

उत्तर

104

आप django.db.transaction.commit_manually को देखना चाहते हैं। बजाय प्रत्येक बचाने के() में,

from django.db import transaction 

@transaction.commit_manually 
def viewfunc(request): 
    ... 
    for item in items: 
     entry = Entry(a1=item.a1, a2=item.a2) 
     entry.save() 
    transaction.commit() 

कौन सा केवल एक बार के लिए प्रतिबद्ध होगा:

http://docs.djangoproject.com/en/dev/topics/db/transactions/#django-db-transaction-commit-manually

तो यह की तरह कुछ होगा।

डीजेंगो 1.3 संदर्भ प्रबंधकों को पेश किया गया था। तो अब आप एक समान तरीके से transaction.commit_on_success() उपयोग कर सकते हैं:

from django.db import transaction 

def viewfunc(request): 
    ... 
    with transaction.commit_on_success(): 
     for item in items: 
      entry = Entry(a1=item.a1, a2=item.a2) 
      entry.save() 

Django 1.4 में, bulk_create जोड़ा गया है, आप अपने मॉडल वस्तुओं की सूची बनाने के लिए और फिर उन्हें एक बार में प्रतिबद्ध करने के लिए अनुमति देता है।

नोट थोक बनाने का उपयोग करते समय सहेजने की विधि नहीं बुलाई जाएगी।

>>> Entry.objects.bulk_create([ 
...  Entry(headline="Django 1.0 Released"), 
...  Entry(headline="Django 1.1 Announced"), 
...  Entry(headline="Breaking: Django is awesome") 
... ]) 

Django 1.6 में, transaction.atomic, पेश किया गया था अब बदलने के लिए विरासत कार्यों commit_on_success और commit_manually इरादा है।

Django documentation on atomic से

:

परमाणु प्रयोग करने योग्य है दोनों एक डेकोरेटर के रूप में:

from django.db import transaction 

@transaction.atomic 
def viewfunc(request): 
    # This code executes inside a transaction. 
    do_stuff() 

और एक संदर्भ प्रबंधक के रूप में:

from django.db import transaction 

def viewfunc(request): 
    # This code executes in autocommit mode (Django's default). 
    do_stuff() 

    with transaction.atomic(): 
     # This code executes inside a transaction. 
     do_more_stuff() 
+7

यह उन्हें मॉडल के रूप में तुरंत चालू करेगा, और हजारों व्यक्तिगत आवेषण चलाएगा। मुझे हमेशा एसक्यूएल में जाना पड़ा और इस प्रकार की मात्रा के लिए मैन्युअल बैच आवेषण करना पड़ा; Django इसके लिए बनाया नहीं गया है। लेकिन हाँ, आप निश्चित रूप से एक लेनदेन चाहते हैं यदि आप इसे इस तरह से कर रहे हैं। –

+0

मैं Django ORM को अच्छी तरह से नहीं जानता, लेकिन क्या ओआरएम सिर्फ आपके लिए एसक्यूएल उत्पन्न नहीं करता है? और बिना किसी विदेशी कुंजी के एक साधारण मॉडल में, एक भी उदाहरण एक एकल सम्मिलन कथन में अनुवाद नहीं करता है? – monkut

+0

हाय क्या आप कृपया .NET के संदर्भ में विस्तृत कर सकते हैं? यह एक बड़ी मदद होगी, क्योंकि मुझे एक ही स्थिति का सामना करना पड़ रहा है –

3

this पर एक नज़र डालें। यह केवल MySQL के साथ आउट ऑफ़ द बॉक्स का उपयोग करने के लिए है, लेकिन अन्य डेटाबेस के लिए क्या करना है इसके बारे में पॉइंटर्स हैं।

3

आप वस्तुओं को थोक लोड करने से बेहतर हो सकते हैं - एक फ़ाइल तैयार करें और थोक लोड टूल का उपयोग करें। यह 8000 व्यक्तिगत आवेषण से काफी अधिक कुशल होगा।

0

मैं सादे एसक्यूएल उपयोग करने की अनुशंसा (नहीं ORM) आप एक ही डालने के साथ कई पंक्तियां डाल सकते हैं:

insert into A select from B; 

आपके एसक्यूएल के बी भाग से चुनें उतना ही जटिल हो सकता है जितना आप चाहते हैं कि परिणाम तालिका ए में कॉलम से मेल खाते हैं और कोई बाधा नहीं है।

-3

मैं एक ही समस्या में भाग गया हूं और मैं इतने सारे आवेषण के बिना ऐसा करने का कोई तरीका नहीं समझ सकता। मैं मानता हूँ कि लेन-देन का उपयोग कर शायद इसे हल करने सही तरीका है, लेकिन यहाँ मेरी हैक है:

def viewfunc(request): 
    ... 
    to_save = []; 
    for item in items: 
     entry = Entry(a1=item.a1, a2=item.a2) 
     to_save.append(entry); 
    map(lambda x: x.save(), to_save); 
+3

यह वास्तव में लूप के भीतर सेव() कॉल करने से अलग नहीं है। मूल रूप से अब आप सभी सहेजने() कॉल करने के लिए दूसरी बार लूप करते हैं। लेकिन Django अभी भी सम्मिलित प्रश्नों की एक ही राशि कर देगा। एकमात्र ऑप्टिमाइज़ेशन एक @monkut वर्णन करता है जिसका मतलब है 'banking.commit_manually'। –

2

आप DSE की जांच करनी चाहिए। मैंने इस तरह की समस्याओं को हल करने के लिए डीएसई लिखा (भारी डालने या अपडेट)। Django orm का उपयोग करना एक मृत अंत है, आपको इसे सादे एसक्यूएल में करना है और डीएसई आपके लिए बहुत अधिक ख्याल रखता है।

थॉमस

+1

एक और बात; यदि आप सादे एसक्यूएल का उपयोग करने का निर्णय लेते हैं और यदि आपके द्वारा डाले गए एसक्यूएल में हर बार एक ही फ़ील्ड है, तो कर्सर.एक्सटेमनी (एसक्यूएल, [प्रविष्टियों की सूची डालने]] का उपयोग करने का प्रयास करें। प्रति प्रविष्टि डालने से बहुत तेज़। – Weholt

2

विशेष रूप से SQLite के संबंध में सवाल का जवाब करने के लिए, के रूप में पूछा है, जबकि मैं अभी-अभी कि bulk_create एक प्रदान करता है इस बात की पुष्टि जबरदस्त गतिशीलता SQLite के साथ एक सीमा है: "डिफ़ॉल्ट रूप से एक बैच में सभी ऑब्जेक्ट्स बनाना है, SQLite को छोड़कर जहां डिफ़ॉल्ट ऐसा है कि अधिकतम 999 चर प्रति क्वेरी का उपयोग किया जाता है।"

उद्धृत सामग्री दस्तावेज़ों से है --- ए -4 ने एक लिंक प्रदान किया।

मुझे जो जोड़ना है वह है कि this djangosnippets अलपर द्वारा प्रविष्टि भी मेरे लिए काम कर रहा है। यह एक छोटा सा रैपर है जो बड़े बैच को तोड़ता है जिसे आप छोटे बैचों में संसाधित करना चाहते हैं, 999 चर सीमा का प्रबंधन करते हैं।

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

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