PHP Сбой запроса выбора PDO на большом количестве записей - PullRequest
0 голосов
/ 11 января 2020

У меня есть база данных PostgreSQL, и мне нужно запросить таблицу, которая содержит 20 миллионов строк. Затем я пу sh результат набора в CSV и, наконец, в S3. Я скомпилировал php скрипт для достижения этой цели. Когда я ограничиваю свой запрос 6 миллионами строк, он успешен, но все, что выше этого, в значительной степени просто кажется неудачным Сообщения об ошибках не регистрируются и не отображаются даже при включенной проверке ошибок и включенных параметрах. Также увеличил объем памяти на моем экземпляре Centos до 3 ГБ и действительно не повезло. Мой код выглядит следующим образом:

//connect to database
$myPDO = new PDO('pgsql:host=127.0.0.1;port=5433;dbname=test', 'test', 'test');
$myPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

//time and memory usage variables
error_reporting(-1);
$time = microtime(TRUE);
$mem = memory_get_usage();

$stmt = $myPDO->prepare("SELECT * FROM table"); 
$stmt->execute(); 

$u = "export.csv";

    $h = fopen($u, "w+");

     $first = true;

     //counter
     $counter = 0;

//loop through all rows
     while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
     $counter++; 

//export column header
     if ($first) {
         fputcsv($h, array_keys($row));
         $first = false;
     }
         //export content
         fputcsv($h, $row);
     }

     fclose($h);

require('AwsS3Upload.php');

//pdo error output
if (!$stmt) {
    echo "\nPDO::errorInfo():\n";
    print_r($dbh->errorInfo());
}
print_r(array('memory' => (memory_get_usage() - $mem) / (1024 * 1024), 'seconds' => microtime(TRUE) - $time));

обновление - рабочий код:

$myPDO = new PDO('pgsql:host=127.0.0.1;port=5433;dbname=test', 'test', 'test');
$myPDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$myPDO->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$myPDO->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

//time and memory usage variables
error_reporting(-1);
$time = microtime(TRUE);
$mem = memory_get_usage();

for($i=0; $i<6; $i++){
    $limit = 5000000;
    $offset = $i * $limit;

$sql = 'SELECT * FROM table ORDER BY :order LIMIT :limit OFFSET :offset';
    $stmt = $myPDO->prepare($sql);
    $stmt->bindParam(':order', $order, PDO::PARAM_INT);
    $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
    $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);

    $stmt->execute(); 

$u = "$i-export.csv";
    $h = fopen($u, "w+");
    $first = true;
    //counter
    $counter = 0;

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $counter++; 

        if ($first) {
            fputcsv($h, array_keys($row));
            $first = false;
        }

            fputcsv($h, $row);
        }

        fclose($h);

   require('AwsS3Upload.php');
}

1 Ответ

1 голос
/ 11 января 2020

Вам придется разбить его на более мелкие кусочки. Как то так:

for($i=0; $i<6; $i++){
    $limit = 5000000;
    $offset = $i * $limit;
    $stmt = $myPDO->prepare("SELECT * FROM table ORDER BY `id` LIMIT $offset,$limit"); 
    $stmt->execute(); 

    // retrieve and write the records into file
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...