2011-05-17 88 views
2

嘿家伙, 我有以下问题: 1进程执行一个非常大的查询并将结果写入文件中,进程应该将状态更新到数据库。python mysqldb多个连接

第一thaught:没问题,伪代码:

db = mysqldb.connect() 
cursor = db.cursor() 
large = cursor.execute(SELECT * FROM VERYLARGETABLE) 
for result in large.fetchall(): 
    file.write(result) 
if timetoUpdateStatus: cursor.execute(UPDATE STATUS) 

问题:听到9万个结果的时候 “大= cursor.execute(SELECT * FROM VERYLARGETABLE)” 从未完成...我想出了一个边界在200万entrys在4列mysql服务器完成查询后30秒,但python进程保持运行几个小时...这可能是一个Python MySQLDB库中的错误..

所以第二次尝试:分贝。使用db.use_results()和fetch_row()查询函数:

db = mysqldb.connect() 
cursor = db.cursor() 
db.query(SELECT * FROM VERYLARGETABLE) 
large = large.use_result() 
while true: 
    for row in large.fetch_row(100000): 
     file.write(row) 
    if timetoUpdateStatus: cursor.execute(UPDATE STATUS) <-- ERROR (2014, "Commands out of sync; you can't run this command now") 

所以第三次尝试是使用2个MySQL连接...哪个不工作,当我打开第一个消失的第二连接....

任何建议??

回答

3

尝试分裂的 “SELECT * FROM数据库” 查询成小块

index=0 
while True: 
    cursor.execute('select * from verylargetable LIMIT %s,%s', (index, index+10000)) 
    records = cursor.fetchall() 
    if len(records)==0: 
      break 
    file.write(records) 
    index+=10000 
file.close() 
+0

是的,这是我的一天 – TekTimmy 2011-05-17 20:00:25

2

使用LIMIT声明中你的大选择:

limit = 0 
step = 10000 
query = "SELECT * FROM VERYLARGETABLE LIMIT %d, %d" 
db = mysqldb.connect() 
cursor = db.cursor() 
while true: 
    cursor.execute(query, (step, limit)) 
    for row in cursor.fetch_all(): 
     file.write(row) 
    if timetoUpdateStatus: 
     cursor.execute(update_query) 
    limit += step 

代码没有进行测试,但你应该明白我的意思。

+0

谢谢,不知道! – TekTimmy 2011-05-17 20:00:41

6

尝试使用MySQL SSCursor。它会将结果集保存在服务器(MySQL数据结构)中,而不是将结果集传输到默认光标所做的客户端(Python数据结构)。使用SSCursor可避免由默认游标试图构建Python数据结构而导致的长时间初始延迟 - 并且为巨大的结果集分配内存。因此,SSCursor也应该需要更少的内存。

import MySQLdb 
import MySQLdb.cursors 
import config 

cons = [MySQLdb.connect(
    host=config.HOST, user=config.USER, 
    passwd=config.PASS, db=config.MYDB, 
    cursorclass=MySQLdb.cursors.SSCursor) for i in range(2)] 
select_cur, update_cur = [con.cursor() for con in cons] 
select_cur.execute(SELECT * FROM VERYLARGETABLE) 
for i, row in enumerate(select_cur): 
    print(row) 
    if i % 100000 == 0 or timetoUpdateStatus: 
     update_cur.execute(UPDATE STATUS) 
+2

这是非常好的,但你需要另一个更新查询连接,因为使用SSCursor需要在执行更多查询之前获取整个结果集。 – ronkot 2014-09-23 10:35:17

+0

@kullero:非常感谢您的纠正。 – unutbu 2014-09-23 11:13:19