我有一个巨大的制表符分隔文件,最多有2亿行(通常约为2000万行)和两列:第一列包含一个ASCII字,最多包含40个字符,第二列包含一个整数。
我想执行以下步骤:
我的内存限制为3 GB(因此将所有数据读入哈希将无效),无限制的硬盘空间并希望在单个内核上运行脚本。我打算并行运行几个脚本,因此硬盘上的读写操作不应该很高。
考虑到文件的大小,应如何继续执行我的脚本(在Perl中)?
考虑到文件大小,您建议在第一步使用哪种算法?
第3步是我认为最复杂的部分。我该怎么处理?我不熟悉索引算法。你能建议一个最适合这个问题的吗?我可以使用任何Perl模块吗?
首先将文件转换为二进制文件(如将SAM转换为BAM)是否有意义?如果是,您是否有任何转换和处理此类文件的说明或算法?
答案 0 :(得分:1)
将整个文件读入SQLite数据库将是我的第一次尝试。
定义表格如下:
create table mytuples (
mykey varchar(40),
myval integer,
constraint tuple_pk primary key(mykey, myval) on conflict ignore
);
使用忽略插入错误的DBI的简单脚本应该这样做。
#!/usr/bin/env perl
use strict; use warnings;
use autodie;
use DBI;
my ($infile) = (@ARGV);
open my $in, '<', $infile;
my $dbh = DBI->connect('dbi:SQLite:some.db', undef, undef, {
AutoCommit => 0,
RaiseError => 0,
},
);
while (my $line = <$in>) {
my ($key, $val) = split ' ', $line;
$dbh->do(q{INSERT INTO mytuples VALUES(?, ?)}, undef, $key, $val);
}
$dbh->commit;
$dbh->disconnect;
对于初始处理,这可能会比命令行上的sort
和grep
慢,但是您可能会感到可以随意使用SQL的灵活性。
答案 1 :(得分:1)
使用系统排序对文件进行排序。最新的GNU Sort有一个并行选项。运行uniq,然后一次读取一行的排序文件,并注意第一列更改的时间很简单。排序使用排序/合并算法,将文件拆分为较小的块进行排序然后合并,因此只要你有足够的磁盘,内存就不是速度问题了。