Frage

Ich habe eine Datei von etwa 30000 Zeilen von Daten, die ich in eine sqlite3 Datenbank laden möchten. Gibt es einen schnelleren Weg, als für jede Zeile von Daten Einfügeanweisungen Erzeugen?

Die Daten sind durch Leerzeichen getrennte und ordnet direkt zu einem sqlite3 Tisch. Gibt es irgendeine Art von Bulk-Insert-Methode für das Hinzufügen von Volumendaten in eine Datenbank?

Hat jemand etwas hinterhältig wunderbare Art und Weise, dies zu tun entwickelt, wenn es in nicht gebaut wird?

Ich soll das Vorwort mit der Frage, gibt es eine C ++, wie es von der API zu tun?

War es hilfreich?

Lösung

Sie können auch versuchen, einige Parameter zwicken aus ihm zusätzliche Geschwindigkeit zu bekommen. Insbesondere möchten Sie wahrscheinlich PRAGMA synchronous = OFF;.

Andere Tipps

  • wickelt alle Einfügungen in einer Transaktion, auch wenn es ein einzelner Benutzer, es ist viel schneller.
  • verwenden vorbereitete Anweisungen.

Sie möchten den .import Befehl verwenden. Zum Beispiel:

$ 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

Beachten Sie, dass diese Bulkbeladung Befehl nicht SQL, sondern eine benutzerdefinierte Funktion von SQLite. Als solches hat es eine seltsame Syntax, weil wir es über echo an die interaktiven Kommandozeileninterpreter vorbei sind, sqlite3.

In PostgreSQL ist das Äquivalent COPY FROM: http://www.postgresql.org/docs/8.1/static/sql -copy.html

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

Eine letzte Sache: Speicher mit dem Wert von .separator vorsichtig zu sein. Das ist ein sehr häufiges Gotcha wenn Bulk-Einsätze zu tun.

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

Sie sollten explizit den Separator gesetzt, bevor Sie .import ein Leerzeichen, Tabulator oder Komma zu sein.

  • Erhöhung PRAGMA default_cache_size zu einer viel größeren Zahl. Dieser Wille erhöht die Anzahl der Seiten im Cache im Speicher.

  • Wickeln Sie alle Einsätze in einer einzigen Transaktion eher als eine Transaktion pro Zeile.

  • Verwenden Sie kompilierten SQL-Anweisungen, die Einsätze zu tun.
  • Schließlich, wie bereits erwähnt, wenn Sie bereit verzichten vollständige ACID Compliance sind, setzen PRAGMA synchronous = OFF;.
  

RE: „Gibt es einen schnelleren Weg, dass für jede Zeile von Daten Einfügeanweisungen Erzeugen“

Erstens: es Schnitt auf 2 SQL-Anweisungen nach unten von Virtuelle Tabellen-API Verwendung von Sqlite3 der Herstellung eg

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

hier Die Idee ist, dass Sie eine C-Schnittstelle implementieren, die die Quelldaten gesetzt liest und präsentieren sie als virtuelle Tabelle auf SQLite und dann tun Sie eine SQL-Kopie von der Quelle in die Zieltabelle in einem Rutsch. Es klingt schwieriger, als es wirklich ist, und ich habe große Verbesserungen in der Geschwindigkeit auf diese Weise gemessen.

Zweitens: Nutzen Sie die anderen raten hier zur Verfügung gestellten heißt die Pragma-Einstellungen und die Verwendung einer Transaktion machen

.

Drittens: Vielleicht sehen, wenn Sie mit einigen der Indizes für die Zieltabelle abschaffen kann. Auf diese Weise SQLite hat weniger Indizes für jede Zeile aktualisieren eingefügt

  

Es gibt keinen Weg zum Masseneinsatz, aber   gibt es eine Möglichkeit, große Teile zu schreiben   in dem Speicher, begehen sie dann an den   Datenbank. Für den C / C ++ API, nur tun:

     

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

     

... (INSERT-Anweisungen)

     

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

db Unter der Annahme, ist die Datenbank-Zeiger.

Ein guter Kompromiss ist Ihren EINSATZ zu wickeln zwischen BEGIN; und Ende; Stichwort heißt:

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

In Abhängigkeit von der Größe der Daten und die Menge an RAM zur Verfügung, eine der besten Performance-Gewinne treten durch SQLite Setzen eine All-in-Memory-Datenbank zu verwenden, anstatt auf der Festplatte geschrieben werden.

In-Memory-Datenbanken, NULL als Dateiname Argument übergeben sqlite3_open und stellen Sie sicher, dass TEMP_STORE definiert ist, in geeigneter Weise

(Alle obigen Text ist aus meiner eigenen Antwort auf eine separaten sqlite- exzerpiert damit verbundene Frage )

ich das eine gute Mischung für einen One-Shot langen Import zu sein gefunden.

.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

Quelle: http: //erictheturtle.blogspot. sein / 2009/05 / am schnellsten Bulk-Import-in-sqlite.html

einige zusätzliche Informationen: http: //blog.quibb .org / 2010/08 / Fast-Bulk-Einsätze-in-sqlite /

Wenn Sie nur einmal einfügen, kann ich einen schmutzigen Trick für Sie haben.

Die Idee ist einfach, zuerst in eine Memory-Datenbank einfügen, dann Backup und schließlich zu Ihrer ursprünglichen Datenbank-Datei wiederherstellen.

Ich schrieb die detaillierten Schritte unter meine Blog . :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top