2011-05-09 40 views
18

Tôi đang "chuyển đổi" tệp CSV lớn (~ 1.6 GB) và chèn các trường cụ thể của CSV vào cơ sở dữ liệu SQLite. Về cơ bản mã của tôi trông giống như:Python CSV to 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)) 

Mọi thứ hoạt động như tôi mong đợi với ngoại lệ ... CNTT mất một khoảng thời gian để xử lý. Tôi có mã hóa không chính xác không? Có cách nào tốt hơn để đạt được hiệu suất cao hơn và hoàn thành những gì tôi cần (chỉ cần chuyển đổi một vài trường của bảng CSV thành bảng SQLite)?

** EDIT - Tôi đã thử nhập trực tiếp csv vào sqlite như được đề xuất nhưng hóa ra tệp của tôi có dấu phẩy trong các trường (ví dụ: "My title, comma"). Đó là tạo lỗi với quá trình nhập. Có vẻ có quá nhiều trong những lần xuất hiện để tự chỉnh sửa các tập tin ...

bất kỳ suy nghĩ khác ?? **

+1

Đó là một tệp lớn. Mât bao lâu? – Blender

+0

Có bao nhiêu bản ghi trùng lặp? Nếu có rất nhiều, có lẽ sẽ nhanh hơn để giữ một 'bộ bản ghi' cục bộ đã được chèn vào và bỏ qua cuộc gọi đến SQL hoàn toàn cho các bản sao. – kindall

+0

[Ở đây] (http://dev.mysql.com/doc/refman/5.5/en/insert-speed.html) là một số mẹo tốc độ tải số lượng lớn của MySQL. – kindall

Trả lời

24

Có thể nhập CSV trực tiếp:

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

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

+1

"blah blah, blah", "123" gây ra vấn đề ... suy nghĩ xung quanh điều này? – user735304

+0

Dường như không có cách thoát tích hợp theo mặc định. Ngoài ra, các dấu ngoặc kép sẽ là các chữ trong chuỗi. Nó có thể có ý nghĩa để thay đổi văn bản bằng cách sử dụng một phân tích cú pháp CSV và xuất ra với một dấu phân cách khác nhau nhưng có thể đánh bại mục đích của việc sử dụng công cụ nhập khẩu ở nơi đầu tiên. – fengb

+0

Hãy thử: .mode csv thay vì .separator, xem: http://stackoverflow.com/questions/14947916/import-csv-to-sqlite/24582022#24582022 – NumesSanguis

3

Thử sử dụng giao dịch.

begin  
insert 50,000 rows  
commit 

Điều đó sẽ cam kết dữ liệu định kỳ thay vì một lần mỗi hàng.

20

Chris là giao dịch sử dụng đúng; chia dữ liệu thành nhiều phần rồi lưu trữ.

"... Trừ khi đã có trong giao dịch, mỗi câu lệnh SQL có giao dịch mới bắt đầu cho giao dịch. Điều này rất tốn kém, vì yêu cầu mở lại, ghi và đóng tệp nhật ký cho mỗi câu lệnh. tránh được bằng cách quấn chuỗi các câu lệnh SQL với BEGIN TRANSACTION; và END GIAO DỊCH; báo cáo tăng tốc này cũng nhận được cho báo cáo mà không làm thay đổi cơ sở dữ liệu "- Nguồn: http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html

" ... có.. một thủ thuật khác mà bạn có thể sử dụng để tăng tốc SQLite: các giao dịch, bất cứ khi nào bạn phải thực hiện nhiều cơ sở dữ liệu, hãy đặt chúng bên trong một giao dịch, thay vì ghi vào và khóa tập tin mỗi lần viết truy vấn được ban hành, ghi sẽ chỉ xảy ra một lần khi giao dịch hoàn tất. "- Nguồn: 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

Một người dùng khác sau mã này gặp sự cố khi cố gắng sử dụng 'len()' với trình đọc CSV của họ: http://stackoverflow.com/questions/18062694/sqlite-transaction-for-csv-importing/18063276#18063276 – rutter

14

Như nó được nói (Chris và Sam), giao dịch làm cải thiện hiệu suất chèn nhiều

Xin vui lòng, hãy để tôi giới thiệu một tùy chọn, sử dụng một bộ các tiện ích Python. để làm việc với CSV, csvkit

để cài đặt:.

pip install csvkit 

để giải quyết vấn đề của bạn

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