使用Python从PostgreSQL中提取二进制大对象 - 开始时的“暂停”
我想从每一行中提取大块数据(blobs),并把它们放到单独的文件里。我用的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行时,我开始注意到脚本启动时有点延迟,就好像数据库在“拍照”,然后再把这张照片“喂”给我。最终的结果就是,过了一段时间没有任何输出,然后大块数据才开始陆续出来。
如果我猜得没错:
- 我很想避免这种“拍照”的过程,因为大块数据本身就很大,这样的“照片”也会很大,给数据库带来负担,还无缘无故地延迟我的输出。
- 我在考虑的一个替代方案是,先读取所有行的ID,把它们放到一个Python数组里,然后遍历这个数组,每次执行一个
select blobColumn where id=...
的查询。这样应该会更好吧?
谢谢任何提示——虽然这涉及到Python、PostgreSQL和psycopg2,但我也想知道这是否是数据库引擎特有的问题,或者我是否错过了更好的使用psycopg2 API的方法等等。
1 个回答
1
试试使用一个叫做 named cursor
的东西。在 psycopg2
中,它的默认值是2000,但你发现500左右是个临界点,所以可以把这个值设置得更低,比如100或200。你只需要在创建游标的时候提供一个名称参数就可以了。
使用 named cursor
后,psycopg2
会自动帮你分批查询,给你设置一个服务器端的 cursor
。在 Python
这边,你照常进行迭代,当需要更多数据时,它会自动从服务器获取。
另外,查看一下大表的 query plan
可能会很有帮助,这样你可以看到它们和小表的区别。
如果你使用了 named cursor
,在执行 execute
后,你只需要 iterate
,而不是调用 fetchone
或类似的东西。
也就是说:
for row in cur:
# do stuff here