【发布时间】:2017-12-11 23:54:04
【问题描述】:
我正在从事一个生物信息学项目,该项目需要我从各种生物体中读取基因组数据(没什么花哨的,只是将其视为字符串)并将其插入数据库。每个读数属于一个生物体,可以包含 5000 到 5000 万个基因,我需要在存储之前对其进行处理和分析。
当前执行此操作的脚本是用 perl 编写的,在所有计算之后,将结果存储在哈希中,如下所示:
$new{$id}{gene_name} = $id;
$new{$id}{gene_database_source} = $gene_database_source
$new{$id}{product} = $product;
$new{$id}{sequence} = $sequence;
$new{$id}{seqlength} = $seqlength;
$new{$id}{digest} = $digest;
$new{$id}{mw} = $mw;
$new{$id}{iep} = $iep;
$new{$id}{tms} = $tms;
读取所有基因后,插入通过哈希循环进入 eval{} 语句。
eval {
foreach my $id (keys %new) {
my $rs = $schema->resultset('Genes')->create(
{
gene_name => $new{$id}{gene_name},
gene_product => $new{$id}{product},
sequence => $new{$id}{sequence},
gene_protein_length => $new{$id}{seqlength},
digest => $new{$id}{digest},
gene_isoelectric_point => $new{$id}{iep},
gene_molecular_weight => $new{$id}{mw},
gene_tmd_count => $new{$id}{tms},
gene_species => $species,
species_code => $spc,
user_id => $tdruserid,
gene_database_source => $new{$id}{gene_database_source}
}
);
};
虽然这个“有效”,但它至少有两个我想解决的问题:
eval 语句旨在对插入进行“故障保护”:如果其中一个插入失败,则 eval 将终止并且不进行任何插入。这显然不是 eval 的工作方式。我很确定所有的插入 直到故障点完成并且没有任何回滚。
脚本需要在非常大的数据集中循环两次(一次在读取和创建哈希时,一次在读取时 哈希并执行插入)。这使得该过程的性能相当差。
我没有创建散列,而是考虑使用 DBIX $schema->new({..stuff..}); 的 new 指令,然后进行大规模插入事务。这将解决双重迭代,并且 eval 可以(或不)与单个事务一起工作,这将执行 的预期行为 ... 有没有办法做到这一点?
【问题讨论】:
-
你是我在这里看到的第一个使用像 DBIC 这样现代的东西的 Bioperl 人。好工作! :)
-
您可以使用 DBIC 进行交易。
-
我不会使用 DBIC 进行批量数据导入。让您的 Perl 脚本创建一个 CSV 或 TSV 并使用您的数据库自己的批量导入功能。
-
如果您按照 Simbabque 的出色回答的建议仍然遇到速度问题,请随时再次发帖,我很高兴看到“Bioperl”编码员在附近:)
标签: mysql perl hash dbix-class