#python #postgresql #blob #psycopg2
#python #postgresql #большой двоичный объект #psycopg2
Вопрос:
Я хочу извлекать большие двоичные объекты из строк внутри отдельных файлов — и использую код Python, который выглядит следующим образом:
connDB = psycopg2.connect(
database=strDbName, user=strUser, password=strPass,
host=strHost, port=strPort)
cur = connDB.cursor()
cmd = """
select id || '.pdf' as filename, blobColumn as binaryData
from someTable
"""
cur.execute(cmd)
while True:
row = cur.fetchone()
if row is None: break
print "Generating:", row[0]
open(row[0], 'w').write(row[1][:])
Это работает нормально, но когда таблица содержит более, например, 500 строк, я начинаю замечать задержку при запуске скрипта — как будто база данных «делает снимок» заранее, а затем «подает» мне этот снимок. Конечным результатом является то, что в течение некоторого времени нет вывода, а затем большие двоичные объекты начинают выливаться.
Если моя догадка верна:
- Я бы очень хотел избежать этой «картинки» — потому что большие двоичные объекты большие, как и «картинка», напрягая БД и задерживая мой вывод без причины.
- Альтернатива, которую я рассматриваю, — это чтение всех идентификаторов строк заранее, добавление их в массив Python, а затем цикл по этому массиву, выполняя по одному
select blobColumn where id=...
на итерацию. Разве это не должно быть лучше?
Спасибо за любые подсказки — и хотя речь идет о Python, PostgreSQL и psycopg2, мне было бы интересно услышать, зависит ли это от движка DB, не упускаю ли я лучшего использования API psycopg2 и т. Д.
Ответ №1:
Попробуйте использовать named cursor
. По умолчанию psycopg2
используется значение 2000, но поскольку вы заметили пороговое значение около 500, попробуйте установить его намного ниже, скажем, 100 или 200. Вы делаете это просто, предоставляя параметр name конструктору cursor.
Это named cursor
позволит psycopg2
автоматически запрашивать пакеты, настроив cursor
для вас серверную часть. С Python
другой стороны, вы просто выполняете итерацию как обычно, и при необходимости она будет получать больше данных с сервера.
Кроме того, может быть полезно взглянуть query plan
на таблицы большего размера, чтобы увидеть, чем они отличаются от таблиц меньшего размера.
Если вы используете named cursor
, после запуска execute
, вы просто iterate
вместо вызова fetchone
или аналогичного.
т.е.
for row in cur:
# do stuff here
Комментарии:
1. Отличное предложение, сработало как шарм. Все, что мне нужно было сделать, это переключиться на «cur = connDB.cursor (name =’test’)», а затем «cur.itersize = 10» — после этого большие двоичные объекты начали появляться мгновенно. Спасибо!