cod*_*ero 1 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)
}
}
Run Code Online (Sandbox Code Playgroud)
我做了一些基准测试,我发现准备/执行部分虽然最初很快,但在多个 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)
Run Code Online (Sandbox Code Playgroud)
以其他方式做会更快吗?我是否应该删除“where”子句并在循环中丢弃我不想要的结果?
谢谢您的帮助。
其他人提出了有用的建议。我只是补充一些我想到的想法......
首先,请参阅我的旧但仍然非常相关的高级 DBI 教程。特别是第 80 页,它解决了对大型结果集进行分页的问题,这与您的情况类似。它还涵盖了分析和fetchrow_hashrefvs bind_columns。
考虑创建一个带有自动增量字段的临时表,通过INSERT ... SELECT ...语句加载你想要的数据,然后在自动增量字段上构建/启用索引(这将比加载已启用索引的数据更快),然后使用键值从该临时表中选择行范围。这对于获取来说会非常快,但是构建临时表会产生前期成本。
考虑在DBD::mysql 中启用mysql_use_result。驱动程序不会将所有行加载到驱动程序的内存中,而是在行从服务器流入时开始将行返回给应用程序。这减少了延迟和内存使用,但以在表上持有锁为代价。
您可以将 using mysql_use_result 与我之前的建议结合使用,但将它与 using 结合可能更简单SELECT SQL_BUFFER_RESULT ...。两者都可以避免锁定问题(无论如何这对您来说可能不是问题)。根据文档,SQL_BUFFER_RESULT“强制将结果放入临时表中”。(琐事:我想我在很多个月前就向蒙蒂建议了 SQL_BUFFER_RESULT。)
| 归档时间: |
|
| 查看次数: |
1753 次 |
| 最近记录: |