Domanda

Consideriamo i seguenti due esempi di codice Python, che ottiene lo stesso, ma con una significativa e sorprendente differenza di prestazioni.

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
cur.execute("SELECT * FROM test for update;")
print ("Finished: SELECT * FROM test for update;: " + str(time.clock() - startTime));
for i in range (100000):
    cur.fetchone()
    cur2.execute("update test set num = num + 1 where current of cursor_unique_name;")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

E

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
for i in range (100000):
    cur2.execute("update test set num = num + 1 where id = " + str(i) + ";")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

L'istruzione CREATE per il test di tabella è:

CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);

E che tabella contiene 100000 righe e VACUUM ANALYZE TEST; è stato eseguito.

ho ottenuto i seguenti risultati costantemente in diversi tentativi.

In primo esempio di codice:

Finished: SELECT * FROM test for update;: 0.00609304950429
Finished: update starting commit: 37.3272754429
Finished: update : 37.4449708474

Secondo esempio di codice:

Finished: update starting commit: 24.574401185
Finished committing: 24.7331461431

Questo è molto sorprendente per me come avrei credo sia dovrebbe essere esattamente l'opposto, il che significa che un aggiornamento utilizzando il cursore dovrebbe essere significativamente più veloce in base alle questa risposta .

È stato utile?

Soluzione

Non credo che il test è balanced- vostro primo codice è il recupero dei dati dal cursore, quindi l'aggiornamento, mentre il secondo è ciecamente aggiornamento per ID senza caricare i dati. Suppongo che la prima sequenza di codice si traduce in un comando FETCH seguito da Update-così che è due / server di turnaround di comando client in contrapposizione a uno.

(anche il primo codice inizia bloccando ogni riga della tavola- questo tira l'intera tabella nella cache- tampone anche pensare a questo proposito, dubito questo impatti prestazioni effettivamente ma non ne ha parlato)

Anche TBH Penso che per una semplice tabella, non ci sarà molto diverso tra aggiornamento da parte ctid (che presumo sia come funziona where current of...) e l'aggiornamento attraverso una a chiave l'aggiornamento pkey primario è una ricerca di indice in più, ma a meno che l'indice è enorme non è molto di un degrado.

Per l'aggiornamento 100.000 righe come questo, ho il sospetto che la maggior parte del tempo è preso per generare le tuple extra e inserendoli in o aggiungendo al tavolo, piuttosto che individuare il tupla precedente per contrassegnare come cancellato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top