【问题标题】:Mysql/python fetchall() can't handle result because it is too bigMysql/python fetchall() 无法处理结果,因为它太大了
【发布时间】:2016-07-15 13:02:42
【问题描述】:

我有一个包含 2,760,000 行的表格。在 mysqlworkbench 中,从原始表中选择 * 需要 36 秒。

我想在 python 中使用这个现有的表创建另一个表(使用 my_func() 来转换值)。

但是,当我在命令行中运行它时,它似乎永远不会完成。

sql = "SELECT ID, Eye, Values FROM my_original_table"
curQuery.execute(sql)

for row in curQuery.fetchall():        
    dat = list(row)
    id = dat.pop(0)
    eye = dat.pop(0)
    values = dat.pop(0)     
    v = my_func(values)
    if v != None :
        sql = "INSERT INTO new_table VALUES ( '%s', '%s', %d );" % (id, eye, v)
    print(sql)
    curExe.execute(sql)

db.commit()

但是,如果我将 LIMIT 0,10 添加到我的第一个选择 sql(如下所示),它运行良好。所以,这意味着我的程序是正确的。但这是否意味着没有“限制”,我的计算机无法处理的数据太多了?我该如何解决这个问题?

sql = "SELECT ID, Eye, Values FROM ETCEpisodeVisualAcuity LIMIT 0,10"

【问题讨论】:

  • 顺便说一句,从不使用字符串格式构造 SQL;使用参数化查询。 (在许多 Python SQL 库中,您可以通过删除查询中 %s 周围的单引号并将最后一个 % 替换为逗号来解决此问题)
  • 270 万行听起来并不那么很多,对吧?
  • 顺便说一句,如果您在 new_table 中有索引,它会在 每个 插入后重建。这需要时间。

标签: python mysql bigdata database


【解决方案1】:

使用游标作为迭代器(不调用fetchall):

sql = "SELECT ID, Eye, Values FROM my_original_table"
curQuery.execute(sql)

for row in curQuery:
    # ...

以上等价于使用带有fetchone的while循环处理查询:

curQuery.execute("SELECT ID, Eye, Values FROM my_original_table")
row = curQuery.fetchone()
while row is not None:
  # do something with data...
  row = curQuery.fetchone()

【讨论】:

  • 感谢您的回答。您的解决方案对我来说更容易阅读。经过我的尝试,程序终于打印出一些结果。然后我实际上在我的“my_func()”中发现了一个错误。但是,在我修复了这个错误之后,它不会再次在命令行上打印任何结果。然后我将 db.commit() 移到 insert 所在的循环中。然后打印终于起作用了。 30 秒后,我可以看到在新表中创建了 40,000 行
【解决方案2】:

根据documentation

db.store_result() 将整个结果集返回给客户端 立即地。如果您的结果集非常大,这可能是 问题。解决此问题的一种方法是在查询中添加 LIMIT 子句, 限制返回的行数。另一种是使用 use_result(),将结果集保存在服务器中并发送 获取时逐行进行。但是,这确实会占用服务器 资源,它束缚了联系:你不能再做任何事情了 查询,直到您获取所有行。一般我推荐 使用 store_result() 除非你的结果集真的很大而且你 由于某种原因无法使用 LIMIT。

db = MySQLdb.connect(yourhost,yourname,yourpw,yourdb)

db.query("SELECT ID, Eye, Values FROM my_original_table")

r=db.use_result()

>>> r.fetch_row()
(('3','2','0'),)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多