Domanda

Ho usato Python con RDBMS '(MySQL e PostgreSQL) e ho notato che davvero non capisco come usare un cursore.

Di solito, uno ha il suo script collegato al DB tramite un DB-API client (come psycopg2 o MySQLdb):

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

E poi si crea un cursore:

cursor = connection.cursor()

E poi si possono inviare query e comandi:

cursor.execute("SELECT * FROM etc")

Ora dov'è il risultato della query, mi chiedo? è sul server? o un po 'sul mio client e un po' sul mio server? E poi, se abbiamo bisogno di accedere ad alcuni risultati, li prendiamo:

rows = cursor.fetchone() 

o

rows = cursor.fetchmany()

Ora diciamo che non recupero tutte le righe e decido di eseguire un'altra query, cosa accadrà ai risultati precedenti? È un loro overhead.

Inoltre, dovrei creare un cursore per ogni forma di comando e riutilizzarlo continuamente per quegli stessi comandi in qualche modo; Io capo psycopg2 può in qualche modo ottimizzare i comandi che vengono eseguiti molte volte ma con valori diversi, come e ne vale la pena?

Thx

È stato utile?

Soluzione

ya, so che ha mesi: P

Il cursore dell'API DB sembra essere strettamente modellato sui cursori SQL. Per quanto riguarda la gestione delle risorse AFA (righe), DB-API non specifica se il client deve recuperare tutte le righe o DICHIARARE un cursore SQL effettivo . Finché le interfacce fetchXXX fanno quello che dovrebbero, DB-API è felice.

I cursori AFA psycopg2 sono interessati (come forse ben saprai), "cursori DB-API senza nome" recupererà l'intero set di risultati - AFAIK bufferizzato in memoria da libpq. " cursori DB-API denominati " (un concetto psycopg2 che potrebbe non essere portatile), richiederà le righe su richiesta (metodi fetchXXX).

Come indicato da " unbenown " ;, execemany può essere utilizzato per ottimizzare più esecuzioni dello stesso comando. Tuttavia, non soddisfa la necessità di dichiarazioni preparate; quando le esecuzioni ripetute di un'istruzione con set di parametri diversi non sono direttamente sequenziali, execemany () eseguirà esattamente come execute (). DB-API "fornisce" autori di driver con la possibilità di memorizzare nella cache le istruzioni eseguite, ma la sua implementazione (qual è lo scopo / la durata dell'istruzione?) non è definita, quindi è impossibile stabilire aspettative nelle implementazioni di DB-API.

Se stai caricando molti dati in PostgreSQL, ti consiglio vivamente di provare a trovare un modo per usare COPY.

Altri suggerimenti

Supponendo che tu stia utilizzando PostgreSQL, i cursori probabilmente sono implementati semplicemente utilizzando l'API del cursore nativa del database. Potresti voler guardare il codice sorgente per pg8000 , un modulo Python PostgreSQL DB-API puro, per vedere come gestisce i cursori. Ti potrebbe piacere anche guardare la documentazione PostgreSQL per i cursori .

Quando guardi qui la mysqldb documentazione puoi vedere che hanno implementato diverse strategie per i cursori. Quindi la risposta generale è: dipende.

Modifica: ecco la documentazione API mysqldb . Ci sono alcune informazioni su come si comporta ogni tipo di cursore. Il cursore standard sta memorizzando il set di risultati nel client. Quindi suppongo che ci sia un sovraccarico se non recuperi tutte le righe dei risultati, perché anche le righe che non recuperi devono essere trasferite al client (potenzialmente sulla rete). La mia ipotesi è che non sia così diverso da postgresql.

Quando si desidera ottimizzare le istruzioni SQL che si chiamano ripetutamente con molti valori, si dovrebbe guardare cursore.executemany (). Prepara un'istruzione SQL in modo che non debba essere analizzata ogni volta che la chiami:

cur.executemany('INSERT INTO mytable (col1, col2) VALUES (%s, %s)',
                [('val1', 1), ('val2', 2)])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top