Eth*_*her 5 perl bind dbi weak-typing
在DBI文档中,这是多次执行查询的推荐代码:
$sth = $dbh->prepare_cached($statement);
$sth->execute(@bind);
$data = $sth->fetchall_arrayref(@attrs);
$sth->finish;
Run Code Online (Sandbox Code Playgroud)
但是,我看到许多*查询方法允许传递一个准备好的和缓存的语句句柄来代替查询字符串,这使得这成为可能:
$sth = $dbh->prepare_cached($statement);
$data = $dbh->selectall_arrayref($sth, \%attrs, @bind);
Run Code Online (Sandbox Code Playgroud)
这种方法有什么问题吗?我还没有看到它在野外使用过.
FWIW,我对这两个实现进行了基准测试.第二种方法fetchall_arrayref在第一次实现selectall_arrayref中使用第二次执行时查询连续两行时,速度略微提高(4%).
*支持此功能的查询方法的完整列表如下:
- selectrow_arrayref - 使用预准备语句的常规方法是fetchrow_arrayref
- selectrow_hashref - ""fetchrow_hashref
- selectall_arrayref - ""fetchall_arrayref
- selectall_hashref - ""fetchall_hashref
- selectcol_arrayref(实际上没有计数,因为它没有使用第一个代码路径的并行方法,如上所述 - 所以使用这个方法的预准备语句的唯一方法是使用上面的第二个代码路径)
它没有任何问题,只要你打算只进行一次获取.使用这些select*_*方法时,所有数据都会以一个块的形式返回.我的DBI代码更像是这样的:
$sth = $dbh->prepare_cached($statement);
$sth->execute(@bind);
while (my $row = $sth->fetch) { # alias for fetchrow_arrayref
# do something with @$row here
}
Run Code Online (Sandbox Code Playgroud)
使用select*_*方法没有相当于此.
如果你打算调用fetchall_*(或者你只获取1行),那么继续使用select*_*带有语句句柄的方法.
不,这种方法没有任何问题。不过,您的基准或其分析有问题。
你已经声称了
$sth->execute(@bind);
$data = $sth->fetchall_arrayref(@attrs);
$sth->finish;
Run Code Online (Sandbox Code Playgroud)
比调用慢
sub selectall_arrayref {
my ($dbh, $stmt, $attr, @bind) = @_;
my $sth = (ref $stmt) ? $stmt : $dbh->prepare($stmt, $attr)
or return;
$sth->execute(@bind) || return;
my $slice = $attr->{Slice}; # typically undef, else hash or array ref
if (!$slice and $slice=$attr->{Columns}) {
if (ref $slice eq 'ARRAY') { # map col idx to perl array idx
$slice = [ @{$attr->{Columns}} ]; # take a copy
for (@$slice) { $_-- }
}
}
my $rows = $sth->fetchall_arrayref($slice, my $MaxRows = $attr->{MaxRows});
$sth->finish if defined $MaxRows;
return $rows;
}
Run Code Online (Sandbox Code Playgroud)
也许如果你摆脱了无用的调用,finish你会发现第一个更快?请注意,差异小于 5% 的基准并不能说明问题;准确率没那么高。
更新:s/快于/慢于/