python 使用流式游标 读取mysql怎么不会内存溢出

使用过java读取mysql大数据量的人应该都知道,如果查询时不开游标不设置一次性区大小的话,会一次性的把所有记录都拉取过来再进行后续操作,数据量一大就很容易出现OOM
如果用python去读取mysql也会遇到同样的问题
那么这么在python中来设置使用游标呢
也很简单
这里使用pymysql来举例子
普通创建mysql链接是这样的
import pymysql db = pymysql.connect("localhost","user","password","dbname" )  cursor = db.cursor() sql = "select * from xxx"try:   cursor.execute(sql)   results = cursor.fetchall()   for row in results:      xxx....except:   pass db.close()
想用游标来控制数据拉取的话,只需要稍加修改就可以
import pymysql db = pymysql.connect("localhost","user","password","dbname",cursorclass=pymysql.cursors.SSCursor )  cursor = db.cursor() sql = "select * from xxx"try:   cursor.execute(sql)   result = cursor.fetchone()   while True:      if result:         xxx....         result = cursor.fetchone()      else:         breakexcept:   pass db.close()
这是一条一条读,当然也可以通过设置fetch的大小来一次读一定量的条数
 
我们来看看cursorclass这个参数是怎么说的
默认值是Cursor,返回的数据是元组形式的
DictCursor,除了返回是词典形式外,其他的与Cursor都相同
SSCursor,是服务端游标,结果集合储存在服务端并且传输行数通过fetch控制,其他与Cursor相同,最好只用在处理很大的数据结果集合上
SSDictCursor,除了返回是词典形式外,其他的与SSCursor相同
 

这里有两点需要注意下:

  1. 使用pymysql.cursors.SSCursor代替默认的cursor。可以使用以上代码,或者这样写:conn.cursor(pymysql.cursors.SSCursor)
  2. 使用fetchone去每次只获得一行,别使用fetchall。也可以使用fetchmay,但是这样其实是多次调用fetchone。

对于SSCursor有一个错误的理解,就是SSCursor是服务端一次性读出所有数据然后一条一条返给客户端,其实不是这样的,这个cursor实际上没有缓存下来任何数据,它不会读取所有所有到内存中,它的做法是从储存块中读取记录,并且一条一条返回给你。这里有一个更适合的名字:流式游标。

因为SSCursor是没有缓存的游标,这里有几条约束:

  1. 这个connection只能读完所有行之后才能处理其他sql。如果你需要并行执行sql,在另外一个connection中执行,否则你会遇到 error 2014 , "Commands out of sync; you can't run this command now."
  2. 必须一次性读完所有行,每次读取后处理数据要快,不能超过60s,否则mysql将会断开这次连接( error2013 , “Lost connection to MySQL server during query),也可以修改 SET NET_WRITE_TIMEOUT = xx 来增加超时间隔。

参考:Techualization: Retrieving million of rows from MySQL(原文更加详细)



整理自:
https://www.jianshu.com/p/80b81a68fd72
https://blog.csdn.net/cowcomic/article/details/82988178

转载于:https://www.cnblogs.com/xibuhaohao/p/10871104.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值