我从选项卡文件导入数百万行,而SQLite .import .mode选项卡非常慢.我有三个索引,所以可能是索引的缓慢.但首先我要检查.import是否将批次/所有这些行分组到一个提交中.我无法找到.import如何工作的文档.有人知道吗?如果索引是问题(我之前遇到过mysql问题)如何在.import结束时禁用它并重新索引?
关注@sixfeetsix评论.
我的架构是:
CREATE TABLE ensembl_vf_b36 (
variation_name varchar(20),
chr varchar(4),
start integer,
end integer,
strand varchar(5),
allele_string varchar(3),
map_weight varchar(2),
flags varchar(50),
validation_status varchar(100),
consequence_type varchar(50)
);
CREATE INDEX pos_vf_b36_idx on ensembl_vf_b36 (chr, start, end);
Run Code Online (Sandbox Code Playgroud)
数据:
rs35701516 NT_113875 352 352 1 G/A 2 NULL NULL INTERGENIC
rs12090193 NT_113875 566 566 1 G/A 2 NULL NULL INTERGENIC
rs35448845 NT_113875 758 758 1 A/C 2 NULL NULL INTERGENIC
rs17274850 NT_113875 1758 1758 1 G/A 2 genotyped cluster,freq INTERGENIC
Run Code Online (Sandbox Code Playgroud)
此表中有15_608_032个条目
这些是统计数据
$ time sqlite3 -separator ' ' test_import.db '.import variations_build_36_ens-54.tab ensembl_vf_b36'
real 29m27.643s
user 4m14.176s
sys 0m15.204s
Run Code Online (Sandbox Code Playgroud)
@sixfeetsix有一个很好的答案,如果你正在读这个,你也会感兴趣
即使所有的优化(参见接受的答案)仍然需要将近30分钟,但如果索引未使用并在末尾添加,则总时间为4分钟:
-- importing without indexes:
real 2m22.274s
user 1m38.836s
sys 0m4.850s
-- adding indexes
$ time sqlite3 ensembl-test-b36.db < add_indexes-b36.sql
real 2m18.344s
user 1m26.264s
sys 0m6.422s
Run Code Online (Sandbox Code Playgroud)
小智 6
我相信,随着越来越多的记录被添加,构建索引的确很慢.根据您拥有的RAM,您可以告诉sqlite使用足够的内存,以便所有这些索引构建活动都在内存中完成(即没有所有I/O,否则会发生内存较少).
对于15M记录,我要说你应该将缓存大小设置为500000.
您还可以告诉sqlite将其事务日志保留在内存中.
最后,您可以将synchronous设置为OFF,以便sqlite永远不会等待写入提交到磁盘.
使用这个我能够将导入15M记录所需的时间除以5(14分钟缩小到2.5),随机GUID的记录分为5列,使用三个中间列作为索引:
b40c1c2f 912c 46c7 b7a0 3a7d8da724c1
9c1cdf2e e2bc 4c60 b29d e0a390abfd26
b9691a9b b0db 4f33 a066 43cb4f7cf873
01a360aa 9e2e 4643 ba1f 2aae3fd013a6
f1391f8b f32c 45f0 b137 b99e6c299528
Run Code Online (Sandbox Code Playgroud)
所以试试这个我建议你把所有的说明放在一些文件中,比如import_test:
pragma journal_mode=memory;
pragma synchronous=0;
pragma cache_size=500000;
.mode tabs
.import variations_build_36_ens-54.tab ensembl_vf_b36
Run Code Online (Sandbox Code Playgroud)
然后尝试一下:
time sqlite3 test_import.db < import_test
Run Code Online (Sandbox Code Playgroud)
编辑
这是回答Pablo(OP)的回答后的评论(它很长时间以作为评论):我(受过教育的)猜测是这样的:
如果我错了,虽然我很高兴听到为什么为了我自己的利益.
编辑2
我在.import期间在索引到位之间进行了比较测试,并在.import完成后立即添加了索引.我使用相同的技术生成由分割随机UUID组成的15M记录:
import csv, uuid
w = csv.writer(open('bla.tab', 'wb'), dialect='excel-tab')
for i in xrange(15000000):
w.writerow(str(uuid.uuid4()).split('-'))
Run Code Online (Sandbox Code Playgroud)
然后我测试了使用之前和之后创建的索引导入(此处创建了索引):
pragma journal_mode=memory;
pragma synchronous=0;
pragma cache_size=500000;
create table test (f1 text, f2 text, f3 text, f4 text, f5 text);
CREATE INDEX test_idx on test (f2, f3, f4);
.mode tabs
.import bla.tab test
Run Code Online (Sandbox Code Playgroud)
所以这里是在之前添加索引的时间:
[someone@somewhere ~]$ time sqlite3 test_speed.sqlite < import_test
memory
real 2m58.839s
user 2m21.411s
sys 0m6.086s
Run Code Online (Sandbox Code Playgroud)
并在以下后添加索引:
[someone@somewhere ~]$ time sqlite3 test_speed.sqlite < import_test
memory
real 2m19.261s
user 2m12.531s
sys 0m4.403s
Run Code Online (Sandbox Code Playgroud)
你看到"用户"时间差(~9s)如何不考虑全时差(~40s)?对我来说,这意味着在之前创建索引时会发生一些额外的I/O,所以我认为所有内容都是在没有额外I/O的内存中完成的.
结论:创建索引后,您将获得更好的导入时间(就像Donal提到的那样).
| 归档时间: |
|
| 查看次数: |
4037 次 |
| 最近记录: |