在sqlite3更快的批量插入?

我有一个约30000行的数据,我想加载到sqlite3数据库的文件。 有没有比为每行数据生成插入语句更快的方法?

数据是空格分隔的,并直接映射到sqlite3表。 是否有任何种类的批量插入方法来添加卷数据到数据库?

有没有人devise了一些非常好的方法来做到这一点,如果它不是内置的?

我应该问这个问题,有没有一个C ++的方法来从API中做到这一点?

你也可以尝试调整一些参数,以获得额外的速度。 具体来说,您可能需要PRAGMA synchronous = OFF;

  • 将所有INSERT包装在一个事务中,即使只有一个用户,也要快得多。
  • 使用准备的语句。

你想使用.import命令。 例如:

 $ 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 

请注意,这个批量加载命令不是SQL,而是SQLite的自定义function。 因此,它有一个奇怪的语法,因为我们通过echo将它传递给交互式命令行解释器sqlite3

在PostgreSQL中相当于COPY FROM : http : //www.postgresql.org/docs/8.1/static/sql-copy.html

在MySQL中,它是LOAD DATA LOCAL INFILE : http : //dev.mysql.com/doc/refman/5.1/en/load-data.html

最后一件事:记住谨慎使用.separator的价值。 在进行批量插入时,这是一个非常常见的问题。

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

在执行.import之前,您应该明确地将分隔符设置为空格,制表符或逗号。

  • PRAGMA default_cache_size增加到更大的数字。 这将增加caching在内存中的页面数量。

  • 将所有插入包装到单个事务中,而不是每行中的一个事务。

  • 使用编译的SQL语句来执行插入。
  • 最后,如前所述,如果您愿意放弃完整的ACID合规性,请将PRAGMA synchronous = OFF;

RE:“是否有更快的方式为每行数据生成插入语句?

第一:通过使用Sqlite3的虚拟表格API,例如,将其削减为2个SQL语句

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

这里的想法是,你实现了一个C接口,它读取你的源数据集,并把它作为一个虚拟表提供给SQlite,然后一次执行从源到目标表的SQL拷贝。 这听起来比实际上更难,我已经用这种方法来测量巨大的速度。

第二:利用这里提供的其他build议,即杂注设置和使用交易。

第三:也许看看你是否可以取消目标表上的一些索引。 这样sqlite将有更less的索引来更新插入的每一行

没有办法批量插入,但有一种方法可以将大块写入内存,然后将它们提交到数据库。 对于C / C ++ API,只需要:

sqlite3_exec(db,“BEGIN TRANSACTION”,NULL,NULL,NULL);

…(INSERT语句)

sqlite3_exec(db,“COMMIT TRANSACTION”,NULL,NULL,NULL);

假设db是你的数据库指针。

一个很好的折衷办法是将你的INSERTS包装在BEGIN之间; 和END; 关键字即:

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

根据数据大小和可用RAM的数量,通过将sqlite设置为使用全内存数据库而不是写入磁盘,可以获得最佳性能收益之一。

对于内存数据库,将NULL作为文件名parameter passing给sqlite3_open , 并确保正确定义了TEMP_STORE

(以上所有文字摘自我个人对sqlite相关问题的回答 )

如果你只是插入一次,我可能对你有一个肮脏的伎俩。

这个想法很简单,首先插入内存数据库,然后备份,最后恢复到您的原始数据库文件。

我在博客上写下了详细的步骤。 🙂

我发现这是一个很好的组合,一次性import。

 .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 

来源: http : //erictheturtle.blogspot.be/2009/05/fastest-bulk-import-into-sqlite.html

一些额外的信息: http : //blog.quibb.org/2010/08/fast-bulk-inserts-into-sqlite/