Python CSV для SQLite - PullRequest
       7

Python CSV для SQLite

20 голосов
/ 10 мая 2011

Я "конвертирую" большой (~ 1,6 ГБ) файл CSV и вставляю определенные поля CSV в базу данных 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))

Все работает так, как я ожидаю, за исключением ... Это занимает невероятное количество времени для обработки.Я неправильно его кодирую?Есть ли лучший способ добиться более высокой производительности и выполнить то, что мне нужно (просто преобразовать несколько полей CSV в таблицу SQLite)?

** РЕДАКТИРОВАТЬ - я пытался напрямую импортировать CSV в SQLiteкак предложено, но оказывается, что мой файл имеет запятые в полях (например, "My title, comma").Это создает ошибки при импорте.Похоже, что этих событий слишком много, чтобы вручную редактировать файл ...

любые другие мысли ?? **

Ответы [ 4 ]

25 голосов
/ 10 мая 2011

Можно импортировать CSV напрямую:

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

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

21 голосов
/ 21 августа 2011

Крис прав - транзакции использования; разделите данные на куски и сохраните их.

" ... Если уже не в транзакции, для каждого оператора SQL запускается новая транзакция. Это очень дорого, поскольку требует повторного открытия, записи и закрытия файла журнала для каждого оператора. этого можно избежать, оборачивая последовательности операторов SQL с помощью операторов BEGIN TRANSACTION и END TRANSACTION; это ускорение также достигается для операторов, которые не изменяют базу данных."- Источник: http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html

" ... есть еще один прием, который можно использовать для ускорения транзакций SQLite: всякий раз, когда вам нужно выполнить несколько операций записи в базу данных, поместите их в транзакцию. Вместо записи (и блокировки) файла каждый и каждый раз, когда выдается запрос на запись, запись будет выполняться только один раз, когда транзакция завершится."- Источник: Насколько масштабируем 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) 
16 голосов
/ 28 марта 2012

Как уже было сказано (Крис и Сэм), транзакции действительно улучшают производительность вставки лота.

Пожалуйста, позвольте мне порекомендовать другой вариант, чтобы использовать набор утилит Python для работы с CSV, csvkit .

Для установки:

pip install csvkit

Чтобы решить вашу проблему

csvsql --db sqlite:///path/to/file.db --insert --table mytable filecsv.txt
3 голосов
/ 11 мая 2011

Попробуйте использовать транзакции.

begin    
insert 50,000 rows    
commit

Это будет фиксировать данные периодически, а не один раз в строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...