English 中文(简体)
PDO/MySQL记忆消耗量大,结果集
原标题:PDO/MySQL memory consumption with large result set
  • 时间:2011-08-01 06:59:39
  •  标签:
  • php
  • mysql
  • pdo

I m having a strange time dealing with selecting from a table with about 30,000 rows.

It seems my script is using an outrageous amount of memory for what is a simple, forward only walk over a query result.

Please note that this example is a somewhat contrived, absolute bare minimum example which bears very little resemblance to the real code and it cannot be replaced with a simple database aggregation. It is intended to illustrate the point that each row does not need to be retained on each iteration.

<?php
$pdo = new PDO( mysql:host=127.0.0.1 ,  foo ,  bar , array(
    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
));
$stmt = $pdo->prepare( SELECT * FROM round );
$stmt->execute();

function do_stuff($row) {}

$c = 0;
while ($row = $stmt->fetch()) {
    // do something with the object that doesn t involve keeping 
    // it around and can t be done in SQL
    do_stuff($row);
    $row = null;
    ++$c;
}

var_dump($c);
var_dump(memory_get_usage());
var_dump(memory_get_peak_usage());

产出:

int(39508)
int(43005064)
int(43018120)

我不理解为什么在几乎不需要随时保存任何数据时,会使用40只记忆。 我已经做了大量工作,用大约6个因素来减少记忆,将“选举后”改为“选举后回家”,但我甚至认为,这种使用率很低,而且表格只会增加。

Is there a setting I m missing, or is there some limitation in PDO that I should be aware of? I m happy to get rid of PDO in favour of mysqli if it can not support this, so if that s my only option, how would I perform this using mysqli instead?

最佳回答

After creating the connection, you need to set PDO::MYSQL_ATTR_USE_BUFFERED_QUERY to false:

<?php
$pdo = new PDO( mysql:host=127.0.0.1 ,  foo ,  bar , array(
    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
));
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

// snip

var_dump(memory_get_usage());
var_dump(memory_get_peak_usage());

产出:

int(39508)
int(653920)
int(668136)

无论结果大小,记忆的使用仍然相当静态。

问题回答

另一种选择是:

$i = $c = 0;
$query =  SELECT home, away FROM round LIMIT 2048 OFFSET %u; ;

while ($c += count($rows = codeThatFetches(sprintf($query, $i++ * 2048))) > 0)
{
    foreach ($rows as $row)
    {
        do_stuff($row);
    }
}

整个成果集(所有30 000分)在你开始研究之前,被缓冲为记忆。

你们应该让数据库做到汇总,只要求数据库提供所需要的两个数字。

SELECT SUM(home) AS home, SUM(away) AS away, COUNT(*) AS c FROM round

现实是,如果你 all一遍,并期望能够把他们全部放到公共卫生和社会福利部,就会一劳永逸地存在。

如果你真的不考虑使用有动力的表述和聚合物,那么你可以考虑限制/放弃你的数据处理。 不要一劳永逸地夺走所有各行:

1)  Fetch 5,000 rows
2)  Aggregate/Calculate intermediary results
3)  unset variables to free memory
4)  Back to step 1 (fetch next set of rows)

Just an idea...

I haven t done this before in PHP, but you may consider fetching the rows using a scrollable cursor - see the fetch documentation for an example.

不要把你的询问的所有结果一回到你的购买力平价,而是把结果放在服务器上,而你则利用一个 cur子通过一个时日子来加以修复。

Whilst I have not tested this, it is bound to have other drawbacks such as utilising more server resources and most likely reduced performance due to additional communication with the server.

Altering the fetch style may also have an impact as by default the documentation indicates it will store both an associative array and well as a numerical indexed array which is bound to increase memory usage.

As others have suggested, reducing the number of results in the first place is most likely a better option if possible.





相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

php return a specific row from query

Is it possible in php to return a specific row of data from a mysql query? None of the fetch statements that I ve found return a 2 dimensional array to access specific rows. I want to be able to ...

Character Encodings in PHP and MySQL

Our website was developed with a meta tag set to... <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> This works fine for M-dashes and special quotes, etc. However, I ...

Pagination Strategies for Complex (slow) Datasets

What are some of the strategies being used for pagination of data sets that involve complex queries? count(*) takes ~1.5 sec so we don t want to hit the DB for every page view. Currently there are ~...

Averaging a total in mySQL

My table looks like person_id | car_id | miles ------------------------------ 1 | 1 | 100 1 | 2 | 200 2 | 3 | 1000 2 | 4 | 500 I need to ...

热门标签