You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pymysql查询含BLOB的大量数据时内存溢出,如何逐行获取BLOB?

解决pymysql查询大BLOB时的内存溢出问题

为什么execute()阶段就内存溢出?

pymysql默认使用的是客户端游标(Client-Side Cursor),当你调用cur.execute()时,MySQL服务器会把整个结果集一次性发送到客户端,并存入本地内存——这就导致哪怕你还没开始迭代或fetch,内存已经被占满了,尤其是BLOB这种大字段,问题会格外明显。

如何逐个获取BLOB?用服务器端游标!

要实现真正的逐行从服务器获取数据,你需要使用服务器端游标(Server-Side Cursor),也就是pymysql.cursors.SSCursor或SSDictCursor。这种游标会让结果集留在MySQL服务器上,每次迭代或调用fetchone()时才获取一行数据,从根本上避免一次性加载所有数据到内存。

修改后的代码示例:

import pymysql
from pymysql.cursors import SSCursor  # 导入服务器端游标

db = pymysql.connect(...)
# 创建游标时指定使用SSCursor
with db.cursor(SSCursor) as cur:
    cur.execute("select value from my_blobs")
    for row in cur:
        # 处理单个BLOB数据
        blob_data = row[0]
        ...

如果需要字典格式的结果,可以用SSDictCursor替换SSCursor。

关于fetchone/迭代游标的用处

你之前的疑惑很合理,这里分两种情况说明:

  • 客户端游标:fetchone/迭代确实是在本地内存的结果集里逐行取,好处是结果集不大时,不用一次性把所有数据加载到变量里,分批处理更灵活,但本质上数据已经在内存里了,解决不了大结果集的内存问题。
  • 服务器端游标:这时候fetchone/迭代才是真正的从服务器逐行拉取数据,这才是你原本期望的“避免内存溢出”的用法。

要不要循环每次查一个BLOB?

完全没必要!循环单条查询会产生大量的数据库请求,严重影响性能。服务器端游标是更高效的方案,既避免内存溢出,又能保持合理的查询效率。

注意事项

  • 使用服务器端游标时,要保持数据库连接处于活跃状态,直到你处理完所有结果。
  • 如果你的查询涉及复杂的排序或分组,MySQL服务器可能还是会在端生成临时表,但对于单纯的大BLOB查询,这个方案依然有效。

内容的提问来源于stack exchange,提问作者P-Gn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:59:21