2009-11-27 29 views
27

Tengo que lidiar con un gran conjunto de resultados (podría haber cientos de miles de filas, a veces más).
Desafortunadamente necesitan ser recuperados todos a la vez (al inicio).¿Cómo utilizar eficientemente el MySQLDB SScursor?

Estoy tratando de hacer eso usando la menor cantidad de memoria posible.
Al mirar en SO he encontrado que usar SSCursor podría ser lo que estoy buscando, pero todavía no sé cómo usarlos exactamente.

Está haciendo un fetchall() desde un cursor de base o un SScursor igual (en términos de uso de memoria)?
¿Puedo 'transmitir' de la secuencia mis filas una por una (o unas pocas) y si es así,
¿cuál es la mejor manera de hacerlo?

Respuesta

28

estoy de acuerdo con la respuesta de Otto Allmendinger, pero para hacer el comentario de explícita Denis Otkidach, aquí es cómo se puede iterar sobre los resultados sin necesidad de utilizar la función de Otto fetch():

import MySQLdb.cursors 
connection=MySQLdb.connect(
    host="thehost",user="theuser", 
    passwd="thepassword",db="thedb", 
    cursorclass = MySQLdb.cursors.SSCursor) 
cursor=connection.cursor() 
cursor.execute(query) 
for row in cursor: 
    print(row) 
+0

Supongo que eso era lo que estaba buscando, gracias – Sylvain

+0

¿Esto trae filas una por una? Si no, ¿cuántas filas trae esto de una vez? Tengo un DB con más de 37 millones de registros. Necesito leer los registros uno por uno y ponerlos en un archivo (con algunas cosas adicionales, así que no puede ser un simple volcado). ¿Se puede hacer esto en paralelo de alguna manera? Por ejemplo, busco 10000 filas, escríbelas y mientras las escribo se van obteniendo algunas filas, y así sucesivamente. – Sohaib

+0

@Sohaib: Esto se obtiene una fila a la vez. Si su problema está vinculado a la CPU, puede usar multiprocesamiento (Python2/3) o concurrent.futures (en Python3) para configurar varios lectores de DB, pero solo debe usar un escritor en el archivo, de lo contrario los registros se obtendrán distorsionado. [Si su problema está vinculado a IO] (http://eli.thegreenplace.net/2012/01/16/python-parallelizing-cpu-bound-tasks-with-multiprocessing/) - si escribir en el archivo es el cuello de botella - luego configurar varios lectores no acelerará el trabajo. – unutbu

9

Utilice definitivamente el SSCursor cuando busque grandes conjuntos de resultados. Hizo una gran diferencia para mí cuando tuve un problema similar. Se puede utilizar de esta manera:

import MySQLdb 
import MySQLdb.cursors 

connection = MySQLdb.connect(
     host=host, port=port, user=username, passwd=password, db=database, 
     cursorclass=MySQLdb.cursors.SSCursor) # put the cursorclass here 
cursor = connection.cursor() 

Ahora se puede ejecutar la consulta con cursor.execute() y utilizar el cursor como un iterador.

Editar: eliminó innecesario iterador de cosecha propia, gracias Denis!

+3

El objeto del cursor es iterable, por lo que no es necesario escribir el generador sobre él. De lo contrario, puede usar 'iter (cursor.fetchone, None)'. –

0

Alternativamente, se puede utilizar SSCursor fuera del objeto de conexión (es muy importante cuando ya define la conexión y no desea que toda la conexión use SSCursor como una clase de cursor).

import MySQLdb 
from MySQLdb.cursors import SSCursor # or you can use SSDictCursor 

connection = MySQLdb.connect(
     host=host, port=port, user=username, passwd=password, db=database) 
cursor = SSCursor(connection) 
cursor.execute(query) 
for row in cursor: 
    print(row) 
Cuestiones relacionadas