【发布时间】:2016-10-08 16:05:07
【问题描述】:
所以我编写了一个脚本来从原始基因组文件中提取数据,原始基因组文件如下所示:
# rsid chromosome position genotype
rs4477212 1 82154 AA
rs3094315 1 752566 AG
rs3131972 1 752721 AG
rs12124819 1 776546 AA
rs11240777 1 798959 AG
rs6681049 1 800007 CC
rs4970383 1 838555 AC
rs4475691 1 846808 CT
rs7537756 1 854250 AG
rs13302982 1 861808 GG
rs1110052 1 873558 TT
rs2272756 1 882033 GG
rs3748597 1 888659 CT
rs13303106 1 891945 AA
rs28415373 1 893981 CC
rs13303010 1 894573 GG
rs6696281 1 903104 CT
rs28391282 1 904165 GG
rs2340592 1 910935 GG
原始文本文件有数十万行,但我只需要特定的行,我需要大约 10,000 行。我有一个 rsid 列表。我只需要每行的基因型。所以我循环遍历 rsid 列表并使用 preg_match 找到我需要的行:
$rawData = file_get_contents('genome_file.txt');
$rsids = $this->get_snps();
while ($row = $rsids->fetch_assoc()) {
$searchPattern = "~rs{$row['rsid']}\t(.*?)\t(.*?)\t(.*?)\n~i";
if (preg_match($searchPattern,$rawData,$matchedGene)) {
$genotype = $matchedGene[3]);
// Do something with genotype
}
}
注意:我删除了很多代码来显示我正在做的正则表达式提取。在进行过程中,我还将每一行插入到数据库中。以下是包含数据库工作的代码:
$rawData = file_get_contents('genome_file.txt');
$rsids = $this->get_snps();
$query = "INSERT INTO wp_genomics_results (file_id,snp_id,genotype,reputation,zygosity) VALUES (?,?,?,?,?)";
$stmt = $ngdb->prepare($query);
$stmt->bind_param("iissi", $file_id,$snp_id,$genotype,$reputation,$zygosity);
$ngdb->query("START TRANSACTION");
while ($row = $rsids->fetch_assoc()) {
$searchPattern = "~rs{$row['rsid']}\t(.*?)\t(.*?)\t(.*?)\n~i";
if (preg_match($searchPattern,$rawData,$matchedGene)) {
$genotype = $matchedGene[3]);
$stmt->execute();
$insert++;
}
}
$stmt->close();
$ngdb->query("COMMIT");
$snps->free();
$ngdb->close();
}
不幸的是,我的脚本运行得很慢。运行 50 次迭代需要 17 秒。所以你可以想象运行 18,000 次迭代需要多长时间。我正在寻找优化这一点的方法。
有没有更快的方法从这个巨大的文本文件中提取我需要的数据?如果我将它分解成一个行数组并使用 preg_grep() 会更快吗?
我尝试将所有 18,000 个 rsid 组合成一个表达式(即 (rs123|rs124|rs125),如下所示:
$rsids = get_rsids();
$rsid_group = implode('|',$rsids);
$pattern = "~({$rsid_group })\t(.*?)\t(.*?)\t(.*?)\n~i";
preg_match($pattern,$rawData,$matches);
但不幸的是,它给了我一些关于超出 PCRE 表达式限制的错误消息。针太大了。我尝试的另一件事是将 S 修饰符添加到表达式中。我读到这会分析模式以提高性能。它根本没有加快速度。也许模式与它不兼容?
那么我需要尝试和优化的第二件事是数据库插入。我添加了一个交易,希望能加快速度,但它根本没有加快速度。所以我在想也许我应该将插入组合在一起,以便我一次插入多行,而不是单独插入它们。
然后我读到另一个想法,使用 LOAD DATA INFILE 从文本文件加载行。在这种情况下,我只需要先生成一个文本文件。我想知道在这种情况下生成文本文件是否会更快。
编辑:似乎占用最多时间的是正则表达式。单独运行程序的那一部分,需要很长时间。 10 行需要 4 秒。
【问题讨论】:
-
只选择您需要的
rsids怎么样?select genotype from table where rsid in('rs4477212', 'etc')将所有 10000 个 ID 放入in。 -
LOAD DATA INFILE会快得多并且是可配置的。然后你可以DELETE * FROM tale WHERE rsid NOT IN (1,2,3)etc... -
你能举一些例子来说明你的
$rawData值吗?请edit您的问题表明这一点。提高程序速度的秘诀在于消除或大幅减少正则表达式的使用。 -
$rawData 变量包含原始基因组文件。我只是使用 file_get_contents($genome_file) 将整个文件加载到一个变量中。
-
另外,我只选择我需要的 rsid。但是每个文件的基因型都是唯一的(每个人都有唯一的 DNA),所以我需要将每个人基因组文件中的基因型加载到数据库中。