¿Cómo funcionan los cursores en la DB-API de Python?

He estado usando python con RDBMS ‘(MySQL y PostgreSQL), y he notado que realmente no entiendo cómo usar un cursor.

Generalmente, uno tiene su script conectado a la base de datos a través de un cliente DB-API (como psycopg2 o MySQLdb):

connection = psycopg2.connect(host='otherhost', etc) 

Y luego uno crea un cursor:

 cursor = connection.cursor() 

Y luego uno puede emitir consultas y comandos:

 cursor.execute("SELECT * FROM etc") 

Ahora, ¿dónde está el resultado de la consulta, me pregunto? ¿Está en el servidor? ¿O un poco en mi cliente y un poco en mi servidor? Y luego, si necesitamos acceder a algunos resultados, los buscamos:

 rows = cursor.fetchone() 

o

 rows = cursor.fetchmany() 

Ahora digamos, no recupero todas las filas y decido ejecutar otra consulta, ¿qué sucederá con los resultados anteriores? Es su una sobrecarga.

Además, debo crear un cursor para cada forma de comando y reutilizarlo continuamente para esos mismos comandos de alguna manera; I head psycopg2 puede de alguna manera optimizar los comandos que se ejecutan muchas veces pero con diferentes valores, ¿cómo y cómo vale la pena?

Gracias

ya sabes que tiene meses: p

El cursor de DB-API parece estar estrechamente modelado después de los cursores SQL. La administración de recursos (filas) de AFA está relacionada, DB-API no especifica si el cliente debe recuperar todas las filas o DECLARAR un cursor SQL real . Mientras las interfaces fetchXXX hagan lo que se supone que deben hacer, DB-API está feliz.

Los cursores AFA psycopg2 están preocupados (como es posible que sepan), los “cursores DB-API sin nombre” obtendrán todo el conjunto de resultados: AFAIK almacenado en la memoria intermedia por libpq. “nombrados cursores DB-API” (un concepto psycopg2 que puede no ser portátil), solicitará las filas a pedido (métodos fetchXXX).

Como se cita en “unbeknown”, se puede usar muchos para optimizar múltiples ejecuciones del mismo comando. Sin embargo, no se adapta a la necesidad de declaraciones preparadas; cuando las ejecuciones repetidas de una statement con diferentes conjuntos de parámetros no son directamente secuenciales, executemany () se desempeñará tan bien como execute (). DB-API “proporciona” a los autores de controladores la capacidad de almacenar en caché las declaraciones ejecutadas, pero su implementación (¿cuál es el scope / vida útil de la statement?) No está definida, por lo que es imposible establecer expectativas en las implementaciones de DB-API.

Si está cargando muchos datos en PostgreSQL, le recomiendo encarecidamente que intente encontrar una forma de usar COPY.

Suponiendo que está utilizando PostgreSQL, los cursores probablemente solo se implementan utilizando la API de cursor nativa de la base de datos. Si lo desea, puede consultar el código fuente de pg8000 , un módulo de DB-API puro de Python PostgreSQL, para ver cómo maneja los cursores. Es posible que también desee consultar la documentación de PostgreSQL para cursores .

Cuando mira aquí la documentación de mysqldb , puede ver que implementaron diferentes estrategias para los cursores. Así que la respuesta general es: depende.

Editar: Aquí está la documentación de la API mysqldb . Hay algo de información sobre el comportamiento de cada tipo de cursor. El cursor estándar está almacenando el conjunto de resultados en el cliente. Entonces, asumo que hay una sobrecarga si no recupera todas las filas de resultados, porque incluso las filas que no obtiene deben transferirse al cliente (potencialmente a través de la red). Mi conjetura es que no es tan diferente de postgresql.

Cuando desee optimizar las sentencias de SQL a las que llama repetidamente con muchos valores, debe mirar cursor.executemany (). Prepara una statement SQL para que no sea necesario analizarla cada vez que la llame:

 cur.executemany('INSERT INTO mytable (col1, col2) VALUES (%s, %s)', [('val1', 1), ('val2', 2)])