2011-05-17 7 views
2

Привет, ребята, У меня проблема: 1 процесс выполняет очень большой запрос и записывает результаты в файл, между процессами должен обновлять статус базы данных.python mysqldb несколько подключений

не

первый священник научил: НЕТ ПРОБЛЕМ, псевдо-код:

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)" никогда не заканчивается ... я понял, граница на 2 миллиона записей в 4 столбцах, где сервер mysql завершил запрос через 30 секунд, но процесс python продолжает работать в течение нескольких часов ... это может быть ошибка в библиотеке MySQLDB Python.

SO SECOND TRY: db. функция запроса с 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") 

так ТРЕТИЙ TRY использовал 2 MySQL соединения ... который не работает, когда я открыть второе соединение первым исчезает ....

какие-либо предложения ??

ответ

3

Try дробя "выберите * из БД" запроса на более мелкие куски

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

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

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

+0

@ kullero: Большое спасибо за исправление. – unutbu