在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/