Вставьте CSV через Pandas в SQLITE: как избежать ошибки памяти? - PullRequest
1 голос
/ 06 марта 2020

Я испытываю ошибку памяти при попытке записи pandas кадра данных из CSV в базу данных SQLITE. Файл CSV имеет 430 МБ и 6 000 000 строк.

Для небольших файлов это работает абсолютно нормально. Однако я хотел бы знать, как избежать ошибки памяти для больших файлов.

Чтение чанками работает нормально и правильно печатает 6 000 000 строк в 20 000 строк. Однако скрипт хочет перенести все 6 000 000 строк в базу данных + таблицу SQLITE и выдает следующую ошибку:

Traceback (most recent call last):
  File "C:/SQLITELOAD1.py", line 42, in <module>
    .rename(columns=dict(zip(big_data.columns, listofcol)))
  File "C:\Python37\site-packages\pandas\util\_decorators.py", line 197, in wrapper
    return func(*args, **kwargs)
  File "C:\Python37\site-packages\pandas\core\frame.py", line 4025, in rename
    return super(DataFrame, self).rename(**kwargs)
  File "C:\Python37\site-packages\pandas\core\generic.py", line 1091, in rename
    level=level)
  File "C:\Python37\site-packages\pandas\core\internals\managers.py", line 170, in rename_axis
    obj = self.copy(deep=copy)
  File "C:\Python37\site-packages\pandas\core\internals\managers.py", line 734, in copy
    do_integrity_check=False)
  File "C:\Python37\site-packages\pandas\core\internals\managers.py", line 395, in apply
    applied = getattr(b, f)(**kwargs)
  File "C:\Python37\site-packages\pandas\core\internals\blocks.py", line 753, in copy
    values = values.copy()
MemoryError

Код:

import csv, sqlite3, time, os, ctypes
from sqlalchemy import create_engine
import pandas as pd
datab = 'NORTHWIND'
con=sqlite3.connect(datab+'.db')
con.text_factory = str  
cur = con.cursor()
koko = 'C:\\NORTHWIND'
print(koko)
directory = koko 
print(directory)

for file in os.listdir(directory):
    for searchfile, listofcol, table in zip(['1251_FINAL.csv'],
                                [['SYS', 'MANDT', 'AGR_NAME', 'OBJECT', 'AUTH', 'FIELD', 'LOW', 'HIGH', 'DELETED']],                  
                                 ['AGR_1251_ALL2']):

                    if file.endswith(searchfile):

                            fileinsert = directory + '\\' + searchfile
                            my_list = []
                            for chunk in pd.read_csv(fileinsert, sep=",",error_bad_lines=False, encoding='latin-1', low_memory=False, chunksize=20000):
                                    my_list.append(chunk)
                                    print(chunk)
                            big_data = pd.concat(my_list, axis = 0)
                            print(big_data)
                            del my_list 
                            (big_data
                             .rename(columns=dict(zip(big_data.columns, listofcol)))
                             .to_sql(name=table,
                                    con=con,
                                     if_exists="replace",
                                     chunksize=20000,
                                     index=False,
                                     index_label=None))

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Когда вы вставляете записи в базу данных SQL, необходимо учитывать два размера:

  • размер отдельного лица INSERT
  • глобальный размер между последовательными COMMIT

Поскольку до тех пор, пока куча запросов не будет принята, база данных должна иметь возможность откатывать все, поэтому ничего не пишется окончательно.

Для описания симптомов я Можно предположить, что to_sql использует параметр chunksize в качестве размера для INSERT, но использует один единственный COMMIT, когда завершается вся операция.

Прямого исправления нет, но обычный способ загрузки большого набор записей в базе данных должен использовать промежуточные COMMIT запросы, чтобы разрешить некоторую очистку в базе данных. Иначе говоря, вы должны использовать один to_sql на чанк. Это заставляет вас явно бросить стол перед l oop, использовать if_exists="append" и быть готовым очистить все, если что-то не так, но я не знаю лучшего способа ...

0 голосов
/ 06 марта 2020

Полагаю, ваш подразумеваемый вопрос - как мне это исправить? Вы можете перефразировать это.

В любом случае, я думаю, что это просто сбой из-за ограничения, и все.

Рассмотрите возможность использования:

if_exists="append"

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