Pregunta

Tengo un archivo de alrededor de 30.000 líneas de datos que desea cargar en una base de datos sqlite3. ¿Hay una manera más rápida que la generación de instrucciones de inserción para cada línea de datos?

Los datos están separados por espacio y asigna directamente a una tabla sqlite3. ¿Hay algún tipo de método de inserción masiva para añadir los datos de volumen a una base de datos?

¿Alguien ha ideado alguna manera sinuosamente maravillosa de hacer esto si no está construido en?

Debería aclarar esto preguntando, ¿hay una manera de C ++ que hacerlo desde la API?

¿Fue útil?

Solución

También puede intentar ajustar algunos parámetros para conseguir velocidad extra fuera de ella. Específicamente es probable que desee PRAGMA synchronous = OFF;.

Otros consejos

  • envolver todos los insertos en una transacción, incluso si hay un solo usuario, que es mucho más rápido.
  • usar comandos preparados.

Usted desea utilizar el comando .import. Por ejemplo:

$ 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

Tenga en cuenta que este comando de carga a granel no es SQL sino más bien una función personalizada de SQLite. Como tal, tiene una sintaxis extraña, porque estamos pasándola a través de echo al intérprete de línea de comandos interactiva, sqlite3.

En PostgreSQL el equivalente es COPY FROM: http://www.postgresql.org/docs/8.1/static/sql -copy.html

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

Una última cosa: recuerde que debe tener cuidado con el valor de .separator. Esa es una de gotcha muy común al hacer las inserciones.

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

Es necesario configurar explícitamente el separador de ser un espacio, ficha, o una coma antes de hacer <=>.

  • Aumentar PRAGMA default_cache_size a un número mucho mayor. Esta voluntad aumentar el número de páginas en caché en la memoria.

  • Envuelva todas las inserciones en una sola transacción en lugar de una transacción por fila.

  • Use compilado de sentencias SQL para hacer las inserciones.
  • Por último, como ya se ha mencionado, si usted está dispuesto renunciar cumplimiento ÁCIDO total, ajuste PRAGMA synchronous = OFF;.
  

RE: "¿Hay una manera más rápida que la generación de instrucciones de inserción para cada línea de datos"

Primero: Córtala a 2 sentencias SQL, haciendo uso de API de tabla virtual de Sqlite3 ejemplo,

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

La idea aquí es que implemente una interfaz C que establecen lee los datos de origen y presentarlo a SQLite como una tabla virtual y luego hacer una copia de SQL desde la fuente a la tabla de destino de una sola vez. Suena difícil de lo que realmente es y lo he medido enormes mejoras en la velocidad de esta manera.

Segundo: Hacer uso de otro consejo aquí proporcionada es decir, la configuración pragma y haciendo uso de una transacción

.

En tercer lugar: Tal vez ver si se puede acabar con algunos de los índices de la tabla de destino. De esa manera sqlite tendrá menos índices de actualización para cada fila insertada

  

No hay manera de inserción masiva, pero   hay una manera de escribir trozos grandes   a la memoria, a continuación, las aprenden de la   base de datos. Para la API de C / C ++, acaba de hacer:

     

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

     

... (instrucciones INSERT)

     

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

Suponiendo db es el puntero de su base de datos.

Un buen compromiso es envolver su inserta entre COMENZAR; y punto; es decir palabra clave:

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

En función del tamaño de los datos y la cantidad de memoria RAM disponible, uno de ocurrirán mediante el establecimiento de SQLite a utilizar una base de datos todo en la memoria en lugar de escribir en el disco las mejores mejoras de rendimiento.

Para bases de datos, pasan a NULL como el argumento de nombre de archivo para sqlite3_open en memoria y asegurarse que TEMP_STORE se define apropiadamente

(Todo el texto anterior es un extracto de mi propia respuesta a una sqlite- separada relacionada pregunta )

Me pareció que para ser una buena mezcla para una larga importación de un disparo.

.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

Fuente: http: //erictheturtle.blogspot. ser / 2009/05 / más rápido de importación masiva-en-sqlite.html

algo de información adicional: http: //blog.quibb .org / 2010/08 / fast-bulk-inserciones-en-sqlite /

Si se acaba de insertar una vez, es posible que tenga un truco sucio por ti.

La idea es simple, primero insertar en una base de datos de memoria, a continuación, copia de seguridad y restaurar finalmente a su archivo de base de datos original.

he escrito los pasos detallados en mi el blog . :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top