mysql - 在 Perl DBI 中处理大量结果的最有效方法是什么?

标签 mysql sql perl dbi

我有一个包含几百万行的表。目前,我正在通过这样做一次处理 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_hashrefbind_columns

  • 考虑创建一个带有自动递增字段的临时表,通过 INSERT ... SELECT ... 语句将所需数据加载到其中,然后在其上构建/启用索引自动增量字段(这比加载已启用索引的数据更快),然后使用键值从该临时表中选择行范围。这对于获取来说将非常很快,但是构建临时表需要前期成本。

  • 考虑启用 mysql_use_resultDBD::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/

相关文章:

MySQL 程序开发而不是发送大查询

mysql - 更改MySQL查询执行顺序

regex - 使用 Perl 正则表达式查找井号 (#)

perl - 如何在 Perl 中的函数调用中将哈希扩展为参数列表?

perl - 为什么Perl的URI提示“无法通过包URI::_ generic找到对象方法” host”?

MySQL REGEX 使用未知长度的 SUBSTRING?

mysql - 根据列以及同一表中存在的空值过滤来自其他表的数据?

mysql - 如何在 ec2 bitnami 上修复 (2002, "Can' t connect to local MySQL server through socket '/tmp/mysql.sock' (2)")?

SQL 在一个查询中统一 COUNT 和 SUM

mysql - 存储两个单词的最佳数据类型?