Проблема с буферизованным запросом PHP PDO - PullRequest
6 голосов
/ 23 февраля 2009

У меня серьезные проблемы с функциями PHP Data Object. Я пытаюсь перебрать большой набор результатов (~ 60 тыс. Строк, ~ 1 гига), используя буферизованный запрос, чтобы избежать выборки всего набора.

Независимо от того, что я делаю, скрипт просто зависает на PDO :: query () - кажется, что запрос выполняется без буферизации (почему иначе изменение размера набора результатов «решило бы» проблему?). Вот мой код для воспроизведения проблемы:

<?php
$Database = new PDO(
    'mysql:host=localhost;port=3306;dbname=mydatabase',
    'root',
    '',
    array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
    )
);

$rQuery = $Database->query('SELECT id FROM mytable');

// This is never reached because the result set is too large
echo 'Made it through.';

foreach($rQuery as $aRow) {
    print_r($aRow);
}
?>

Если я ограничу запрос каким-либо разумным числом, он будет работать нормально:

$rQuery = $Database->query('SELECT id FROM mytable LIMIT 10');

Я попытался поиграть с PDO :: MYSQL_ATTR_MAX_BUFFER_SIZE, а также с помощью PDO :: prepare () и PDO :: execute () (хотя в приведенном выше запросе нет параметров), но оба безрезультатно. Любая помощь будет оценена.

Ответы [ 3 ]

8 голосов
/ 23 февраля 2009

Если я правильно понимаю, буферизованные запросы включают в себя сообщение PHP о том, что вы хотите дождаться полного набора результатов, прежде чем начинать обработку. До PDO это было по умолчанию, и вам нужно было позвонить mysql_unbuffered_query, если вы хотите немедленно обработать результаты.

Почему это не объясняется на странице драйвера PDO MySQL, я не знаю.

1 голос
/ 23 февраля 2009

Вы можете попытаться разделить его на куски, которые недостаточно велики, чтобы вызвать проблемы:

<?php    
$id = 0;
$rQuery = $Database->query('SELECT id FROM mytable ORDER BY id ASC LIMIT 100');

do {
    stuff($rQuery);
    $id += 100;
} while ( $rQuery = $Database->query(
            'SELECT id FROM mytable ORDER BY id ASC LIMIT 100 OFFSET '.$id
          )
        );
?>

... в любом случае, вы поняли идею.

0 голосов
/ 23 апреля 2012

Или, может быть, вы могли бы попробовать вместо этого функции mysql:

while ($row = mysql_fetch_row($query)) {
...
}

Что, безусловно, будет быстрее, так как этот оператор foreach производит впечатление использования fetchAll() вместо fetch() каждой строки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...