【问题标题】:PHP PDO select query failing on large amount of recordsPHP PDO选择查询在大量记录上失败
【发布时间】:2020-04-28 21:56:18
【问题描述】:

我有一个 PostgreSQL 数据库,我需要查询一个包含 2000 万行的表。然后我将结果集推送到 csv 中,最后推送到 S3 中。我已经编译了一个 php 脚本来实现这一点。当我将查询限制为 600 万行时,它会成功,但高于此的任何内容似乎都失败了。即使启用了所有错误检查和参数,也不会记录或显示错误消息。还将我的 Centos 实例上的内存增加到 3GB,但真的没有运气。我的代码如下:

//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');
}

【问题讨论】:

    标签: php postgresql pdo


    【解决方案1】:

    你必须把它分成小块。像这样的:

    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
    }
    

    【讨论】:

    • thx 看起来我们现在正朝着正确的方向前进。但是现在我遇到了一个问题,我的id 列实际上是字符串类型并收到错误:提示:没有运算符与给定的名称和参数类型匹配。您可能需要添加显式类型转换。我没有建立数据库,也无法控制列类型
    • 让它工作。将在上面发布工作代码。有人可以评论一下吗?
    • 嘿,我有非常大量的数据,可能有几百万行我想做的是循环 array_push() 并将所有结果存储在一个变量中,但变量没有保存在服务器上记录超过 150 万,但在本地运行良好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多