2013-08-13 14 views
13

ho letto questo: Importing a CSV file into a sqlite3 database table using PythonInserimento di massa dati enorme in SQLite utilizzando Python

e sembra che tutti suggerisce di utilizzare la linea per linea la lettura invece di utilizzare .import massa da SQLite. Tuttavia, ciò renderà l'inserimento molto lento se disponi di milioni di righe di dati. C'è un altro modo per aggirare questo?

Aggiornamento: Ho provato il seguente codice per inserire riga per riga, ma la velocità non è buona come mi aspettavo. Esiste un modo per migliorarlo

for logFileName in allLogFilesName: 
    logFile = codecs.open(logFileName, 'rb', encoding='utf-8') 
    for logLine in logFile: 
     logLineAsList = logLine.split('\t') 
     output.execute('''INSERT INTO log VALUES(?, ?, ?, ?)''', logLineAsList) 
    logFile.close() 
connection.commit() 
connection.close() 

risposta

17

Dividi i tuoi dati in blocchi al volo utilizzando le espressioni del generatore, crea inserti all'interno della transazione. Ecco una citazione da sqlite optimization FAQ:

A meno che già in una transazione, ogni istruzione SQL ha un nuovo un'operazione iniziata per questo. Questo è molto costoso, poiché richiede la riapertura, la scrittura e la chiusura dello file journal per ciascuna istruzione . Questo può essere evitato avvolgendo sequenze di istruzioni SQL con BEGIN TRANSACTION; e FINE TRANSAZIONE; dichiarazioni. Questa accelerazione si ottiene anche per istruzioni che non alterano il database.

Here's come può essere il tuo codice.

Inoltre, sqlite ha una capacità di import CSV files.

+0

SQLite può importare molti file CSV contemporaneamente. Non sono riuscito a trovare un modo per farlo? – Shar

+0

Non pensare che sia possibile importare molti file csv contemporaneamente. Dividere i dati in blocchi e inserirli nelle transazioni dovrebbe essere la strada da percorrere, credo. – alecxe

+0

Grazie! Penso che andrò con quello. – Shar

14

Sqlite può fare tens of thousands of inserts per second, basta assicurarsi di fare tutto di loro in una singola transazione circondando gli inserti con BEGIN e COMMIT. (executemany() esegue automaticamente.)

Come sempre, non ottimizzare prima di sapere che la velocità sarà un problema. Provare prima la soluzione più semplice e ottimizzare solo se la velocità è inaccettabile.

+0

Grazie! Ci sto provando proprio ora e riferirò sulla velocità. – Shar

+0

Ho appena provato ciò che hai suggerito inserendo riga per riga. La velocità non è male, ma non è ancora così veloce come spero che sia. Forse il mio codice non era abbastanza ben scritto. L'ho aggiornato nella domanda sopra. Hai qualche suggerimento? – Shar

23

Poiché questo è il risultato principale di una ricerca su Google, ho pensato che sarebbe stato utile aggiornare questa domanda.

Dal python sqlite docs è possibile utilizzare

import sqlite3 

persons = [ 
    ("Hugo", "Boss"), 
    ("Calvin", "Klein") 
] 

con = sqlite3.connect(":memory:") 

# Create the table 
con.execute("create table person(firstname, lastname)") 

# Fill the table 
con.executemany("insert into person(firstname, lastname) values (?,?)", persons) 

Ho usato questo metodo per commettere più di 50k inserti fila alla volta ed è estremamente veloce.

+1

È lampo anche perché stai usando sqlite come database in memoria ... – aramaki

+0

ha diminuito l'attività di creazione di 2 minuti in meno di un secondo! ed è un database di file, quindi è comunque un fulmine – Math

Problemi correlati