c++ - 在sqlite3中更快的批量插入?




insert bulk (7)

RE:“有没有更快的方法为每行数据生成插入语句?”

第一:通过使用Sqlite3的Virtual table 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复制。 它听起来比实际更难,我用这种方式测量了巨大的速度改进。

第二:利用此处提供的其他建议,即编译指示设置和使用交易。

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

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

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

如果它没有内置,有没有人设计出一些狡猾的好方法呢?

我应该先问一下,有没有一种C ++方法可以从API中做到这一点?


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

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

......(INSERT语句)

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

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


如果您只是插入一次,我可能会有一个肮脏的技巧。

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

我在博客上写了详细的步骤。 :)


您想使用.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的自定义功能。 因此它有一个奇怪的语法,因为我们通过echo将它传递给交互式命令行解释器sqlite3

在PostgreSQL中,等效的是COPY FROMhttp://www.postgresql.org/docs/8.1/static/sql-copy.htmlhttp://www.postgresql.org/docs/8.1/static/sql-copy.html

在MySQL中,它是LOAD DATA LOCAL INFILEhttp://dev.mysql.com/doc/refman/5.1/en/load-data.htmlhttp://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之前,应该将分隔符显式设置为空格,制表符或逗号。


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

对于内存数据库,将NULL作为sqlite3_open的filename参数传递, 并确保正确定义TEMP_STORE

(以上所有文字摘自我自己对单独的sqlite相关问题的回答


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


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

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

  • 使用编译的SQL语句来执行插入操作。
  • 最后,如前所述,如果您愿意放弃完全符合ACID,请设置PRAGMA synchronous = OFF;




bulk