вставка большого элемента в sqlite3 db на python - ошибка памяти - PullRequest
0 голосов
/ 07 января 2011

Я делаю численное моделирование в Python, приводящее к довольно большим объектам данных (приблизительно 200 МБ). Я пишу их в sqlite3 БД. После увеличения разрешения (и, следовательно, размера данных) примерно на 20% я получаю ошибку памяти при попытке вставить в БД. Работал просто отлично с меньшим разрешением раньше. Вот фрагмент кода:

def write_to_db(self, filename, dataObject, name) :
    connection  = sqlite.connect(filename)
    cursor      = connection.cursor()
    cursor.execute("CREATE TABLE pulses (ID INTEGER PRIMARY KEY, name STRING, data BLOB)")
    cursor.execute("INSERT INTO pulses(name, data) VALUES (?, ?)", (dataObjectName, sqlite.Binary(pickle.dumps(dataObject))))
    connection.commit()
    connection.close()

Я работаю под winXP, 1 ГБ ОЗУ, подкачка 3 ГБ (и не получил уведомления Windows о необходимости расширения подкачки), Python 2.6.

Заранее спасибо за помощь. Тим

Ответы [ 2 ]

1 голос
/ 09 января 2011

Обратите внимание, что XP будет увеличивать своп только в меньших приращениях. Если ваша программа внезапно попытается использовать намного больше памяти и недостаточно подкачки, вы получите ошибку памяти.

SQLite будет отлично работать с каплями размером до 1 ГБ, и вы обычно можете использовать 2 ГБ. Однако у вас не хватит адресного пространства в 32-битном процессе.

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

Вы можете решить свою непосредственную проблему, выполнив следующие действия:

  • Переключиться на использование 64 бит. Microsoft продает семейный пакет Windows 7, который включает в себя обновления для 3 экземпляров XP / Vista за 150 долларов США (по цене 130 долларов США), чтобы вы могли обновить несколько компьютеров. Таким образом вы можете переключиться с 32-битной XP на 64-битную Win 7. Простое выполнение этой задачи немедленно решит вашу проблему, даже если вы не измените объем оперативной памяти и т. Д.

  • Добавьте -1 к вызову pickle, который говорит ему использовать самый последний протокол pickle, который использует двоичный код, а не кодировку по умолчанию ascii. В результате вы получите меньше данных. Прочтите документ для получения дополнительной информации о версиях протокола и о том, какие версии Python их поддерживают.

  • Также сжимайте протравленные данные - например, bz2.compress (pickle.dumps (obj, -1)

Наиболее вероятная причина возникновения проблем - нехватка адресного пространства. 32-разрядный процесс, как правило, может одновременно обрабатывать только 2 ГБ данных, и различные исполняемые файлы и общие библиотеки, стеки для каждого потока, кэш SQLite и т. Д. Также вычитаются из этого пространства. Вам нужно будет внимательно относиться ко всем различным элементам данных, которые у вас есть, и к моменту их появления. Вызов del и gc.collect () после их упреждающего использования поможет уменьшить количество одновременно используемых данных.

0 голосов
/ 10 января 2011

Вы спрашиваете в комментарии о возможных альтернативных механизмах хранения. Если данные, которые вы храните, составляют пятую часть доступной оперативной памяти, я бы сказал, что вам нужно очень осторожно управлять памятью, поскольку вы не можете скопировать данные до того, как закончите их использовать; и в любом случае вы будете убивать производительность. Возможно, вам удастся добиться того, чтобы sqlite правильно делал с вами BLOB-объекты, поскольку они могут быть большими.

Похоже, вы используете sqlite в качестве простого хранилища ключей / значений. Вы рассматривали возможность использования плоских файлов? Если вам нужен ATOMicity, вы все равно можете использовать базу данных sqlite, чтобы определить, какие файлы в вашем хранилище простых файлов являются действительными. Вы можете безопасно сделать это, фиксируя данные в БД только после чистой записи всех простых файлов, и удаляя плоские файлы только после фиксации соответствующего удаления в БД.

Чтобы это работало, вам понадобится механизм для сериализации dataObject в объект типа файла в Python. Pickle может сделать это для вас, если вы передадите ему объект типа файла, но я подозреваю, что он все равно будет весьма неэффективным.

Вы говорите, что делаете численное моделирование; Вы знаете о NumPy? numpy массивы поддерживают функцию tofile, которая будет более эффективной, чем травление, и вы можете получить значительное повышение производительности в своих симуляциях, если вы еще не используете ее.

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