迭代DB表中所有行的最佳方法

Oem*_*erA 14 python mysql database

我经常编写很少的Python脚本来遍历DB表的所有行.例如,向所有订户发送电子邮件.

我是这样做的

conn = MySQLdb.connect(host = hst, user = usr, passwd = pw, db = db)
cursor = conn.cursor()
subscribers = cursor.execute("SELECT * FROM tbl_subscriber;")

for subscriber in subscribers:
 ...

conn.close()
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更好的方法可以做到这一点,因为我的代码可能会将数千行加载到内存中.

我想过用它可以做得更好LIMIT.也许是这样的:

"SELECT * FROM tbl_subscriber LIMIT %d,%d;" % (actualLimit,steps)    
Run Code Online (Sandbox Code Playgroud)

什么是最好的方法呢?你会怎么做?

aar*_*ing 38

除非你有BLOB,否则数千行不应成为问题.你知道吗?

此外,为什么通过做类似的事情给自己和整个家庭带来耻辱

"SELECT * FROM tbl_subscriber LIMIT %d,%d;" % (actualLimit,steps)
Run Code Online (Sandbox Code Playgroud)

当光标以避免SQL注入的方式替换你时?

c.execute("SELECT * FROM tbl_subscriber LIMIT %i,%i;", (actualLimit,steps))
Run Code Online (Sandbox Code Playgroud)

  • @pyfunc.我的生活中写了太多PHP.如果没有畏缩,我无法查看不安全的代码. (9认同)

dug*_*res 16

您不必修改查询,可以使用游标的fetchmany方法.我是这样做的:

def fetchsome(cursor, some=1000):
    fetch = cursor.fetchmany
    while True:
        rows = fetch(some)
        if not rows: break
        for row in rows:
            yield row  
Run Code Online (Sandbox Code Playgroud)

这样你就可以"SELECT*FROM tbl_subscriber;" 但你一次只会取一些.


And*_*rew 7

出于性能原因,大多数基于libmysqlclient的MySQL连接器将默认缓冲客户端内存中的所有结果(假设您不会读取大型结果集).

当您确实需要在MySQLdb中读取大结果时,可以使用SSCursor来避免缓冲整个大型结果集.

http://mysql-python.sourceforge.net/MySQLdb.html#using-and-extending

SSCursor - "服务器端"游标.像Cursor一样但使用CursorUseResultMixIn.仅在处理可能较大的结果集时使用.

这确实会引入您必须小心的并发症.如果您没有从游标中读取所有结果,则第二个查询将引发ProgrammingError:

>>> import MySQLdb
>>> import MySQLdb.cursors
>>> conn = MySQLdb.connect(read_default_file='~/.my.cnf')
>>> curs = conn.cursor(MySQLdb.cursors.SSCursor)
>>> curs.execute('SELECT * FROM big_table')
18446744073709551615L
>>> curs.fetchone()
(1L, '2c57b425f0de896fcf5b2e2f28c93f66')
>>> curs.execute('SELECT NOW()')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/site-packages/MySQLdb/cursors.py", line 173, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib64/python2.6/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now")
Run Code Online (Sandbox Code Playgroud)

这意味着您必须始终在发出另一个之前从游标(以及可能的多个结果集)中读取所有内容--MySQLdb不会为您执行此操作.