Domanda

Ho un file di circa 30000 righe di dati che voglio caricare in un database sqlite3.C'è un modo più veloce rispetto alla produzione di una insert per ogni riga di dati?

I dati sono delimitati da spazi e le mappe direttamente ad un sqlite3 tabella.C'è qualche sorta di bulk insert metodo per l'aggiunta di un volume di dati in un database?

Qualcuno ha ideato alcuni ovviamente modo meraviglioso di fare questo se non è integrato?

Devo questa premessa per chiedere, c'è un C++ modo per farlo da API?

È stato utile?

Soluzione

Si può anche provare tweaking alcuni parametri per ottenere velocità extra fuori di esso. In particolare, probabilmente si desidera PRAGMA synchronous = OFF;.

Altri suggerimenti

  • avvolgere tutti gli inserti in una transazione, anche se c'è un singolo utente, è molto più veloce.
  • utilizzare le istruzioni preparate.

Si desidera utilizzare il comando .import. Ad esempio:

$ cat demotab.txt
44      92
35      94
43      94
195     49
66      28
135     93
135     91
67      84
135     94

$ echo "create table mytable (col1 int, col2 int);" | sqlite3 foo.sqlite
$ echo ".import demotab.txt mytable"  | sqlite3 foo.sqlite

$ sqlite3 foo.sqlite
-- Loading resources from /Users/ramanujan/.sqliterc
SQLite version 3.6.6.2
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from mytable;
col1    col2
44      92
35      94
43      94
195     49
66      28
135     93
135     91
67      84
135     94

Si noti che questo comando caricamento di massa non è SQL, ma piuttosto una funzione personalizzata di SQLite. Come tale ha una sintassi strano perché stiamo passando via echo alla interattivo riga di comando interprete, sqlite3.

In PostgreSQL l'equivalente è COPY FROM: http://www.postgresql.org/docs/8.1/static/sql -copy.html

In MySQL si è LOAD DATA LOCAL INFILE: http://dev.mysql.com/doc/refman/5.1 /en/load-data.html

Un'ultima cosa: ricordarsi di stare attenti con il valore di .separator. Questo è un Gotcha molto comune quando si fa inserti di massa.

sqlite> .show .separator
     echo: off
  explain: off
  headers: on
     mode: list
nullvalue: ""
   output: stdout
separator: "\t"
    width:

Si dovrebbe impostare in modo esplicito il separatore ad essere uno spazio, scheda o virgola prima di fare <=>.

  • Aumenta PRAGMA default_cache_size a un numero molto più grande. Questo sarà aumentare il numero di pagine cache in memoria.

  • Avvolgere tutti gli inserti in una singola transazione piuttosto che una transazione per riga.

  • compilato istruzioni SQL per fare gli inserti.
  • Infine, come già accennato, se si è disposti rinunciare piena conformità ACID, impostare PRAGMA synchronous = OFF;.

RE:"C'è un modo più veloce che la generazione di istruzioni insert per ogni riga di dati?"

Primo:Tagliare verso il basso per 2 istruzioni SQL facendo uso di Sqlite3 s Tabella virtuale API ad es.

create virtual table vtYourDataset using yourModule;
-- Bulk insert
insert into yourTargetTable (x, y, z)
select x, y, z from vtYourDataset;

L'idea qui è che si implementa un'interfaccia C che legge il tuo set di dati di origine e di presentarlo al SQlite come una tabella virtuale e poi fare un SQL copia dall'origine alla tabella di destinazione in uno andare.Sembra più difficile di quello che realmente è, e l'ho misurato miglioramenti di velocità enorme in questo modo.

Secondo:Fare uso di altri consigliano di cui qui es.pragma impostazioni e facendo uso di una transazione.

Terzo:Forse vedere se si può fare via con alcuni indici della tabella di destinazione.Che modo sqlite hanno meno di indici di aggiornamento per ogni riga inserita

  

Non c'è modo di inserimento di massa, ma   c'è un modo per scrivere pezzi di grandi dimensioni   a memoria, poi impegnarsi per la   Banca dati. Per l'API C / C ++, basta fare:

     

sqlite3_exec (db, "BEGIN TRANSAZIONE",   NULL, NULL, NULL);

     

... (istruzioni INSERT)

     

sqlite3_exec (db, "COMMIT TRANSACTION", null, null, null);

Supponendo db è il puntatore del database.

Un buon compromesso è quello di avvolgere le INSERTI tra BEGIN; e fine; cioè parola chiave:

BEGIN;
INSERT INTO table VALUES ();
INSERT INTO table VALUES ();
...
END;

A seconda della dimensione dei dati e la quantità di RAM disponibile, uno dei accadranno impostando SQLite per utilizzare un database all-in-memory, piuttosto che la scrittura su disco i migliori guadagni di prestazioni.

Per in-memory database, passare NULL come argomento il nome del file per sqlite3_open e assicurarsi che TEMP_STORE è definita opportunamente

(Tutto il testo di cui sopra è tratto dalla mia risposta a una sqlite- separata domanda relativa )

Ho trovato questo per essere un buon mix per un lungo importazione un solo colpo.

.echo ON

.read create_table_without_pk.sql

PRAGMA cache_size = 400000; PRAGMA synchronous = OFF; PRAGMA journal_mode = OFF; PRAGMA locking_mode = EXCLUSIVE; PRAGMA count_changes = OFF; PRAGMA temp_store = MEMORY; PRAGMA auto_vacuum = NONE;

.separator "\t" .import a_tab_seprated_table.txt mytable

BEGIN; .read add_indexes.sql COMMIT;

.exit

fonte: http: //erictheturtle.blogspot. essere / 2009/05 / veloce-bulk-import-into-sqlite.html

alcune informazioni aggiuntive: http: //blog.quibb .org / 2010/08 / fast-bulk-inserti-in-sqlite /

Se sono solo inserendo una volta, io possa avere un trucco sporco per voi.

L'idea è semplice, prima di inserire in un database di memoria, quindi il backup e, infine, il ripristino per il file di database originale.

ho scritto i passaggi dettagliati a mia blog . :)

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