2013-05-24 11 views
15

Ho bisogno di incrementare i valori in una colonna periodicamente con i dati che ricevo in un file. La tabella ha> 400000 righe. Finora, tutti i miei tentativi hanno prodotto prestazioni molto scarse. Ho scritto un esperimento che rispecchia le mie esigenze:sqlalchemy bulk performance problemi di aggiornamento

#create table 
engine = create_engine('sqlite:///bulk_update.db', echo=False) 
metadata = MetaData() 

sometable = Table('sometable', metadata, 
    Column('id', Integer, Sequence('sometable_id_seq'), primary_key=True), 
    Column('column1', Integer), 
    Column('column2', Integer), 
) 

sometable.create(engine, checkfirst=True) 

#initial population 
conn = engine.connect() 
nr_of_rows = 50000 
insert_data = [ { 'column1': i, 'column2' : 0 } for i in range(1, nr_of_rows)] 
result = conn.execute(sometable.insert(), insert_data) 

#update 
update_data = [ {'col1' : i, '_increment': randint(1, 500)} for i in range(1, nr_of_rows)] 

print "nr_of_rows", nr_of_rows 
print "start time : " + str(datetime.time(datetime.now())) 

stmt = sometable.update().\ 
     where(sometable.c.column1 == bindparam('col1')).\ 
     values({sometable.c.column2 : sometable.c.column2 +  bindparam('_increment')}) 

conn.execute(stmt, update_data) 

print "end time : " + str(datetime.time(datetime.now())) 

le volte che ottengo sono questi:

nr_of_rows 10000 
start time : 10:29:01.753938 
end time : 10:29:16.247651 

nr_of_rows 50000 
start time : 10:30:35.236852 
end time : 10:36:39.070423 

così facendo un 400000+ quantità di righe ci vorrà troppo tempo.

Sono nuovo di sqlalchemy, ma ho letto molto doc e non riesco a capire cosa sto facendo male.

grazie in anticipo!

risposta

13

Si sta utilizzando l'approccio corretto effettuando l'aggiornamento collettivo con una singola query.

Il motivo per cui occorre tanto tempo è perché la tabella non ha indice su sometable.column1. Ha solo l'indice primario sulla colonna id.

La query di aggiornamento utilizza sometable.column1 nella clausola where per identificare il record. Quindi il database deve analizzare tutti i record della tabella per ogni singolo aggiornamento della colonna.

Per effettuare l'aggiornamento correre molto più velocemente è necessario aggiornare il codice definizione dello schema tabella per aggiungere la creazione dell'indice alla definizione column1 con , index=True:

sometable = Table('sometable', metadata, 
    Column('id', Integer, Sequence('sometable_id_seq'), primary_key=True), 
    Column('column1', Integer, index=True), 
    Column('column2', Integer), 
) 

ho testato codice aggiornato nella mia macchina - ci sono voluti < 2 secondi per far funzionare il programma.

Complimenti BTW alla descrizione della domanda - si inserisce tutto il codice necessario per riprodurre il problema.

+0

grande, grazie! Avevo sentito parlare di indicizzazione, ma pensavo che entrasse in gioco solo con volumi molto più grandi. Tutto chiaro ora, evviva! – devboell