Python в Windows: большое количество вставок с использованием pyodbc вызывает утечку памяти - PullRequest
3 голосов
/ 03 ноября 2010

Я пытаюсь заполнить базу данных MS SQL 2005, используя python на windows.Я вставляю миллионы строк, а на 7 миллионов я использую почти гигабайт памяти.Приведенный ниже тест съедает 4 мегабайта ОЗУ на каждые вставленные строки по 100 КБ:

import pyodbc
connection=pyodbc.connect('DRIVER={SQL Server};SERVER=x;DATABASE=x;UID=x;PWD=x')
cursor=connection.cursor()
connection.autocommit=True
while 1:
    cursor.execute("insert into x (a,b,c,d, e,f) VALUES (?,?,?,?,?,?)",1,2,3,4,5,6)
mdbconn.close()

Решение проблемы с хаком: в итоге я создал новый процесс с использованием многопроцессорного модуля для возврата памяти.Все еще не понимаете, почему вставка строк таким способом потребляет так много памяти.Есть идеи?

Ответы [ 5 ]

8 голосов
/ 18 июня 2011

У меня была такая же проблема, и она выглядит как проблема pyodbc с параметризованными вставками: http://code.google.com/p/pyodbc/issues/detail?id=145

Временное переключение на статическую вставку с заполненным предложением VALUES устраняет утечку, пока я не попробую выполнитьисточник тока.

1 голос
/ 31 мая 2011

Даже я сталкивался с той же проблемой.

Мне пришлось читать более 50 файлов XML каждый по 300 МБ и загружать их в SQL Server 2005.

Я попробовал следующее:

Использование того же курсора для разыменования.

Закрытие / открытие соединения

Установка соединения в None.

В конце концов загрузился каждый файл XML, загруженный с помощьюМодуль процесса.

Теперь я заменил процесс, используя IronPython - System.Data.SqlClient.

Это дает лучшую производительность и лучший интерфейс.

0 голосов
/ 04 ноября 2010

Попробуйте создать отдельный курсор для каждой вставки.Повторно используйте переменную курсора каждый раз в цикле, чтобы неявно разыменовать предыдущий курсор.Добавляйте connection.commit после каждой вставки.

Вам может понадобиться только что-нибудь простое, например time.sleep (0) внизу каждого цикла, чтобы запустить сборщик мусора.

0 голосов
/ 17 ноября 2010

Вы также можете попытаться форсировать сборку мусора время от времени с помощью gc.collect() после импорта модуля gc.

Другим вариантом может быть использование cursor.executemany() и проверка, очищает ли этопроблема.Однако против executemany() неприятно то, что она принимает последовательность, а не итератор (поэтому вы не можете передать ее генератору).Сначала я бы попробовал сборщик мусора.

РЕДАКТИРОВАТЬ: Я только что проверил код, который вы опубликовали, и я не вижу той же проблемы.Вы используете старую версию pyodbc?

0 голосов
/ 03 ноября 2010

Может быть, закрыть и заново открыть соединение каждые миллионы строк или около того?

Конечно, это ничего не решает, но если вам нужно сделать это только один раз, вы сможете продолжить жизнь!

...