我有一些看起来像这样的东西:
my $report = new ReportGenerator; #custom object
my $dbh = $dbc->prepare('SELECT * FROM some_table WHERE some_condition'); #DBI handle
$dbh->execute();
while(my $href = $dbh->fetchrow_hashref){
$report->process_record($href);
}
$dbh->finish();
print $report->printReport();
我的问题是循环的每次迭代都很慢。问题是MySQL。我想知道是否有可能在while循环中放置某种包装器以使其一次获取多个记录,同时,将所有记录提取到内存中也是不实际的。我并不担心代码的效率(hashref vs arrayref等)。相反,我有兴趣一次提取10000条记录。
该数据库有大约500万条记录。我无法更改/升级服务器。
由于
答案 0 :(得分:8)
您可以使用接受'maxrows'参数的fetchall_arrayref函数:
while (my $data = $dbc->fetchall_arrayref(undef, 10000)) {
for my $row( @{$data} ) {
$report->process_record($row);
}
}
您还可以查看RowCacheSize属性,该属性尝试控制从驱动程序中获取的返回记录数。
答案 1 :(得分:4)
哪一点很慢?是execute
,fetchrow_hashref
还是process_record
的来电? fetchrow_hashref
问题似乎不太可能。它更有可能是执行查询或process_record
的黑匣子。
但这一切都在猜测。这里真的不可能有所帮助。我建议您使用Devel::NYTProf获取有关代码性能的实际数据。
答案 2 :(得分:3)
使用DBI将行提取为哈希的最快方法是使用bind_columns()
,如下所示:
$sth->execute;
my %row;
$sth->bind_columns( \( @row{ @{$sth->{NAME_lc} } } ));
while ($sth->fetch) {
print "$row{region}: $row{sales}\n";
}
如果您对每一行重用相同的哈希感到满意,那么这是唯一合适的。
除此之外,我同意davorg,避免猜测:先测量。
有关使用DBI的更多信息,包括性能,请参阅我的tutorial slides(从2007年开始,但仍然相关)。