Perl:为包含两列的选项卡文件创建索引

时间:2012-04-08 13:59:53

标签: database perl indexing binary samtools

我有一个巨大的制表符分隔文件,最多有2亿行(通常约为2000万行)和两列:第一列包含一个ASCII字,最多包含40个字符,第二列包含一个整数。

我想执行以下步骤:

  1. 按第一栏排序
  2. 删除重复的行以使所有行都是唯一的
  3. 读出第一栏中给定条目的所有行
  4. 我的内存限制为3 GB(因此将所有数据读入哈希将无效),无限制的硬盘空间并希望在单个内核上运行脚本。我打算并行运行几个脚本,因此硬盘上的读写操作不应该很高。

    考虑到文件的大小,应如何继续执行我的脚本(在Perl中)?

    考虑到文件大小,您建议在第一步使用哪种算法?

    第3步是我认为最复杂的部分。我该怎么处理?我不熟悉索引算法。你能建议一个最适合这个问题的吗?我可以使用任何Perl模块吗?

    首先将文件转换为二进制文件(如将SAM转换为BAM)是否有意义?如果是,您是否有任何转换和处理此类文件的说明或算法?

2 个答案:

答案 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;

对于初始处理,这可能会比命令行上的sortgrep慢,但是您可能会感到可以随意使用SQL的灵活性。

答案 1 :(得分:1)

使用系统排序对文件进行排序。最新的GNU Sort有一个并行选项。运行uniq,然后一次读取一行的排序文件,并注意第一列更改的时间很简单。排序使用排序/合并算法,将文件拆分为较小的块进行排序然后合并,因此只要你有足够的磁盘,内存就不是速度问题了。