我有一个包含几百万行的表。目前,我正在通过这样做一次处理 10,000 个:
for (my $ival = 0; $ival < $c_count; $ival += 10000)
{
my %record;
my $qry = $dbh->prepare
( "select * from big_table where address not like '%-XX%' limit $ival, 10000");
$qry->execute();
$qry->bind_columns( \(@record{ @{$qry->{NAME_lc} } } ) );
while (my $record = $qry->fetch){
this_is_where_the_magic_happens($record)
}
}
我做了一些基准测试,我发现准备/执行部分虽然最初很快,但在多个 10,000 行批处理后速度会大大降低。这是一种愚蠢的写法吗?我只知道如果我试图一次性选择所有内容,这个查询将永远持续下去。
这是日志中的一些片段:
(Thu Aug 21 12:51:59 2014) Processing records 0 to 10000
SQL Select => 1 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
(Thu Aug 21 12:52:13 2014) Processing records 10000 to 20000
SQL Select => 1 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
(Thu Aug 21 12:52:25 2014) Processing records 20000 to 30000
SQL Select => 2 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
(Thu Aug 21 12:52:40 2014) Processing records 30000 to 40000
SQL Select => 5 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
(Thu Aug 21 12:52:57 2014) Processing records 40000 to 50000
SQL Select => 13 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
...
(Thu Aug 21 14:33:19 2014) Processing records 650000 to 660000
SQL Select => 134 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU)
(Thu Aug 21 14:35:50 2014) Processing records 660000 to 670000
SQL Select => 138 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
(Thu Aug 21 14:38:27 2014) Processing records 670000 to 680000
SQL Select => 137 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
(Thu Aug 21 14:41:00 2014) Processing records 680000 to 690000
SQL Select => 134 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
采用其他方式会更快吗?我是否应该删除“where”子句并在循环中丢弃我不想要的结果?
感谢您的帮助。
最佳答案
其他人提出了有用的建议。我只会添加一些想到的想法......
首先,请看我的旧版但仍然非常相关Advanced DBI Tutorial .特别是第 80 页,它解决了通过大型结果集进行分页的问题,这与您的情况类似。它还涵盖分析和
fetchrow_hashref
与bind_columns
。考虑创建一个带有自动递增字段的临时表,通过
INSERT ... SELECT ...
语句将所需数据加载到其中,然后在其上构建/启用索引自动增量字段(这比加载已启用索引的数据更快),然后使用键值从该临时表中选择行范围。这对于获取来说将非常很快,但是构建临时表需要前期成本。考虑启用 mysql_use_result在 DBD::mysql .驱动程序不会将所有行加载到驱动程序的内存中,而是在行从服务器流入时开始将行返回给应用程序。这减少了延迟和内存使用,但以持有表锁为代价。
您可以结合使用 mysql_use_result 和我之前的建议,但结合使用
SELECT SQL_BUFFER_RESULT ...
可能更简单。两者都可以避免锁定问题(无论如何这对您来说可能不是问题)。每the docs , SQL_BUFFER_RESULT “强制将结果放入临时表”。 (琐事:我想我很久以前就向 Monty 建议了 SQL_BUFFER_RESULT。)
关于mysql - 在 Perl DBI 中处理大量结果的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25434015/