7

PHP データ オブジェクト関数で深刻な問題が発生しています。セット全体のフェッチを避けるために、バッファリングされたクエリを使用して、かなり大きな結果セット (~60k 行、~1gig) をループしようとしています。

私が何をしても、スクリプトは 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() も使用してみました (ただし、上記のクエリにはパラメーターはありません)、どちらも役に立ちませんでした。どんな助けでも大歓迎です。

4

3 に答える 3

9

私がこの権利を理解していれば、バッファリングされたクエリには、処理を開始する前に結果セット全体を待機することを PHP に指示することが含まれます。PDO より前は、これがデフォルトでありmysql_unbuffered_query、結果をすぐに処理したい場合は呼び出す必要がありました。

これが PDO MySQL ドライバー ページで説明されていない理由はわかりません。

于 2009-02-23T18:39:10.327 に答える
2

問題が発生するほど大きくないチャンクに分割してみることができます。

<?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
          )
        );
?>

...とにかく、あなたはアイデアを得る。

于 2009-02-23T18:35:09.960 に答える
-1

または、代わりに mysql 関数を試すこともできます。

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

fetchAll()その foreach ステートメントは代わりにfetch()各行を使用する印象を与えるため、これは間違いなく高速になります

于 2012-04-23T19:47:19.287 に答える