使用Python从PostgreSQL中提取二进制大对象 - 开始时的“暂停”

0 投票
1 回答
726 浏览
提问于 2025-04-18 10:13

我想从每一行中提取大块数据(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

撰写回答