2010-08-05 169 views
-1

我正在处理一个数据库,其中行数在1,000,000以上。我有我的选择声明,但如果我首先尝试,我会很快耗尽内存。这里是我的2个问题:Perl DBI取数据库的一部分?

  1. 因为我不知道要启动的数据库的确切大小,有没有办法找出数据库的大小而不做使用fetchall?电脑从字面上不能支持它。

  2. 是否有任何方式来获取说某个数据库的块,可能一次处理5000个,而不是为每一行都做一个单独的fetchrow?我刚刚完成了一项测试,并且一行一行地完成了测试,其每1000行的工作时间差不多只有4分钟,而老板对于要花费近3天才能完成的程序并不看好。

这是我的代码:

while ($i < $rows) 
{ 
    if ($i + $chunkRows < $rows) 
    { 
     for ($j = 0; $j < $chunkRows; $j++) 
     { 
      @array = $sth->fetchrow(); 
      ($nameOne, $numberOne, $numberTwo) = someFunction($lineCount,@array,$nameOne,$numberOne, $numberTwo); 
     } 
    } 
    else #run for loop for j < rows % chunkrows 
    $i = $i + $j 
} 
+0

我想拉回一排行,希望能够减少超过一百万个单独行上调用fetchRow的时间。 – ThePirateSheep 2010-08-05 19:00:50

+0

你使用什么数据库?不同的数据库对这个问题会有不同的答案。 – 2010-08-05 19:17:19

+0

我使用DBI,我看到的唯一提取是fetchRow()和fetchall的空构造函数。我正在寻找一个fetchRows(0,5000),其中0将作为开始的行,5000将是要获取的行数或沿着这些行的数据 – ThePirateSheep 2010-08-05 19:23:52

回答

0

要获取表中的行数,你可以使用

Select count(*) from Table

要限制行数返回,这可能特定于您的数据库。例如,MySQL有一个Limit关键字,它可以让你只返回一定数量的行。这就是说,如果你拉回所有行,你可能想在这里添加一些其他问题来具体描述你在做什么,因为这在大多数应用程序中并不常见。

如果你的数据库中没有limit可用,你可以做一些事情,比如用一个布尔值标记一列来指示一行已经被处理,然后重新运行你的查询来限制行数,跳过那些已完成。或者记录处理的最后一行id,然后将下一个查询限制为具有较大id的行。有很多方法。

+0

所以我最终通过伯爵搞乱了我的生活,这让我的生活变得更轻松。我有一个选择计数(1),只是从来没有正确的语法。 我不相信DBI中有一个限制类型的关键字,这正是我正在使用的。 此外,我没有访问权限来更新数据库,因为这些数据来自外部来源。查看数据库是如何以及如何对其进行排序的,唯一按顺序(如行ID或某事)是一个时间戳,但数据库中可能有多个相同的时间戳。我正在寻找从0开始的获取(0,5000),并且需要5000 – ThePirateSheep 2010-08-05 18:56:54

+0

我的想法是,程序需要3天的原因是由于每个获取都是单独的,并且每次被调用时是我的延迟和花费的大部分时间。我不知道我是否可以尽我所能地解释它:/ – ThePirateSheep 2010-08-05 18:58:18

+1

DBI不是数据库,它是perl数据库*接口*。你要查找的是查看你连接的实际数据库服务器是否有LIMIT关键字。你在使用什么数据库服务器? 如果你不能写入数据库......你可以写入一个文件吗?查询行,将信息写入文件,然后处理文件中的每一行。这可能会降低内存使用量。或者,对你有权写入的第二个表执行同样的操作。 – GrandmasterB 2010-08-05 20:03:40

1

显示您的fetchrow循环代码;可能有办法改进它,这取决于你如何调用它,以及你对数据的处理方式。

我相信大多数数据库的数据库驱动程序会一次从服务器获取多行数据;你将不得不说出你正在使用哪种数据库来获得良好的建议。如果它确实与每一行的服务器进行通信,那么您将不得不一次修改SQL以获取一组行,但如何实现这一点取决于您使用的数据库。

啊,DB2。我不确定,但我认为你必须这样做:

SELECT * 
FROM (SELECT col1, col2, col3, ROW_NUMBER() OVER() AS RN FROM table) AS cols 
WHERE RN BETWEEN 1 AND 10000; 

并调整每个查询的数字,直到得到一个空的结果。显然这个 是更多的工作在数据库端让它重复多次查询;我不知道是否有DB2优化方法(即临时表)。