2011-05-09 10 views
18

मैं एक बड़ी (~ 1.6 जीबी) सीएसवी फ़ाइल "कनवर्ट करना" और CSV के विशिष्ट फ़ील्ड को SQLite डेटाबेस में सम्मिलित कर रहा हूं। अनिवार्य रूप से मेरी कोड लगता है:पाइथन सीएसवी को SQLite

import csv, sqlite3 

conn = sqlite3.connect("path/to/file.db") 
conn.text_factory = str #bugger 8-bit bytestrings 
cur = conn.cur() 
cur.execute('CREATE TABLE IF NOT EXISTS mytable (field2 VARCHAR, field4 VARCHAR)') 

reader = csv.reader(open(filecsv.txt, "rb")) 
for field1, field2, field3, field4, field5 in reader: 
    cur.execute('INSERT OR IGNORE INTO mytable (field2, field4) VALUES (?,?)', (field2, field4)) 

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

** संपादित करें - मैंने सीएसवी को सीधे एसक्लाइट में आयात करने की कोशिश की है, लेकिन यह पता चला है कि मेरी फाइल फ़ील्ड में अल्पविराम है (उदा। "My title, comma")। यह आयात के साथ त्रुटियां पैदा कर रहा है। ऐसा प्रतीत होता है उन घटनाओं की भी कई मैन्युअल फ़ाइल को संपादित करने देखते हैं ...

किसी अन्य विचार ?? **

+1

यह एक बड़ी फाइल है। इसमें कितना समय लगता है? – Blender

+0

कितने डुप्लिकेट रिकॉर्ड हैं? यदि बहुत कुछ है, तो संभवत: पहले से डाले गए रिकॉर्ड्स के स्थानीय 'सेट' को रखने के लिए तेज़ होगा, और पूरी तरह से डुप्लिकेट के लिए कॉल को एसक्यूएल पर छोड़ दें। – kindall

+0

[यहां] (http://dev.mysql.com/doc/refman/5.5/en/insert-speed।एचटीएमएल) कुछ MySQL थोक लोड गति युक्तियाँ हैं। – kindall

उत्तर

24

यह सीधे सीएसवी आयात करने के लिए संभव है:

sqlite> .separator "," 
sqlite> .import filecsv.txt mytable 

http://www.sqlite.org/cvstrac/wiki?p=ImportingFiles

+1

"ब्ला ब्लाह, ब्लाह", "123" समस्याएं पैदा करता है ... इस के आसपास के विचार? – user735304

+0

ऐसा प्रतीत नहीं होता है कि डिफ़ॉल्ट रूप से भागने का एक अंतर्निहित तरीका है। साथ ही, उद्धरण स्ट्रिंग के भीतर अक्षर होंगे। एक सीएसवी पार्स का उपयोग करके पाठ को बदलने और एक अलग विभाजक के साथ आउटपुट करने का अर्थ हो सकता है लेकिन यह पहले स्थान पर आयात उपकरण का उपयोग करने के उद्देश्य को हरा सकता है। – fengb

+0

कोशिश करें: .separator के बजाय .mode csv, देखें: http://stackoverflow.com/questions/14947916/import-csv-to-sqlite/24582022#24582022 – NumesSanguis

3

लेनदेन का उपयोग करने का प्रयास करें।

begin  
insert 50,000 rows  
commit 

यह प्रति पंक्ति एक बार के बजाय समय-समय पर डेटा करेगा।

20

क्रिस सही उपयोग लेनदेन है; डेटा को टुकड़ों में विभाजित करें और फिर इसे स्टोर करें।

"... जब तक पहले से ही एक लेनदेन में, प्रत्येक SQL विवरण एक नई लेन-देन के लिए यह शुरू कर दिया है। यह बहुत महंगा है, क्योंकि यह दोबारा खुलने की आवश्यकता है, के लिए लिख, और प्रत्येक कथन के लिए पत्रिका फ़ाइल को बंद करने। यह कर सकते हैं लेन-देन में शुरू के साथ SQL कथन के दृश्यों लपेटकर से बचा जा, और समाप्ति लेन-देन, बयान इस speedup भी बयान जो डेटाबेस में परिवर्तन नहीं करते के लिए प्राप्त की है "- स्रोत: http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html

" ... वहाँ है।। एक और चाल जिसका उपयोग आप SQLite को तेज करने के लिए कर सकते हैं: लेन-देन। जब भी आपको एकाधिक डेटाबेस लिखना पड़ता है, तो उन्हें लेनदेन के अंदर रखें। फ़ाइल को प्रत्येक बार लिखने (और लॉक करने) के बजाय लिखने की क्वेरी जारी की जाती है, लेखन केवल तभी होगा जब लेनदेन पूरा हो जाए। "- स्रोत: How Scalable is SQLite?

import csv, sqlite3, time 

def chunks(data, rows=10000): 
    """ Divides the data into 10000 rows each """ 

    for i in xrange(0, len(data), rows): 
     yield data[i:i+rows] 


if __name__ == "__main__": 

    t = time.time() 

    conn = sqlite3.connect("path/to/file.db") 
    conn.text_factory = str #bugger 8-bit bytestrings 
    cur = conn.cur() 
    cur.execute('CREATE TABLE IF NOT EXISTS mytable (field2 VARCHAR, field4 VARCHAR)') 

    csvData = csv.reader(open(filecsv.txt, "rb")) 

    divData = chunks(csvData) # divide into 10000 rows each 

    for chunk in divData: 
     cur.execute('BEGIN TRANSACTION') 

     for field1, field2, field3, field4, field5 in chunk: 
      cur.execute('INSERT OR IGNORE INTO mytable (field2, field4) VALUES (?,?)', (field2, field4)) 

     cur.execute('COMMIT') 

    print "\n Time Taken: %.3f sec" % (time.time()-t) 
+0

इस कोड का अनुसरण करने वाला कोई अन्य उपयोगकर्ता उपयोग करने का प्रयास करने में समस्या में भाग गया उनके सीएसवी पाठक के साथ 'लेन() ': http://stackoverflow.com/questions/18062694/sqlite-transaction-for-csv-importing/18063276#18063276 – rutter

14

के रूप में यह कहा गया है (क्रिस और सैम), लेन-देन एक बहुत डालने के प्रदर्शन में सुधार करना

कृपया, मुझे एक और विकल्प की अनुशंसा अजगर उपयोगिताओं का एक सूट का उपयोग करने दें। सीएसवी, csvkit के साथ काम करने

स्थापित करने के लिए:।

pip install csvkit 

अपनी समस्या को हल करने के लिए

csvsql --db sqlite:///path/to/file.db --insert --table mytable filecsv.txt