2016-07-15 19 views
0

我有一个2,760,000行的表。在mysqlworkbench中,从原始表中选择*需要36秒。我想在Python中使用这个现有的表创建另一个表(使用my_func()来转换值)。Mysql/python fetchall()无法处理结果,因为它太大

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

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" 
+0

顺便说一句,从未构造SQL用字符串格式化;使用参数化查询。 (在许多Python SQL库中,只需删除查询中%s的单引号,并用逗号代替最后一个%,就可以在代码中修复此问题) – geoffspear

+0

270万行听不到** * *很多,对吗? –

+0

顺便说一句,如果你在'new_table'中有一个索引,它会在* every *插入之后被重建。这需要时间。 –

回答

1

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'),) 
+0

感谢您的回答。 – wildcolor

2

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

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

for row in curQuery: 
    # ... 

以上等同于处理使用而循环带fetchone的查询:

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() 
+0

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