首页 文章

PDO PHP Postgres:缓慢获取数据

提问于
浏览
-1

我在PostgreSQL 9.2.4上玩PDO,并试图从一个有数百万行的表中获取数据 . 我的查询返回大约100.000行 . 我没有使用任何PDOStatements的fetch函数,我只是使用PDO Objecte itels的结果并循环遍历它 . 但它随着时间的推移越来越慢 . 一开始它的读取速度就像每秒200行 . 但它接近尾声时,它变慢了 . 现在在第30.000行,它每秒只获取1行 . 它为什么变慢 .

我这样做,非常简单:

$dbh = new PDO("pgsql...");
$sql = "SELECT x, y FROM point WHERE name is NOT NULL and place IN ('area1', 'area2')";
$res = $dbh->query($sql);
$ins_sql = "INSERT INTO mypoints (x, y) VALUES ";
$ins_vals = [];
$ins_placeholders = [];
foreach($res as $row) {
  $ins_placeholders[] = "(?,?)"; 
  $ins_vals = array_merge($ins_vals, [$row['x'], $row['y']]);
  printCounter();
}

// now build up one insert query using placeholders and values, 
// to insert all of them in one shot into table mypoints

函数printCounter只是增加一个int var并打印它 . 所以我可以看到它在我创建插入语句之前已经在该数组中放了多少行 . 我使用一次性插入来加快速度,比使用100,000次插入更好 . 但是,foreach循环越来越慢 . 我怎样才能提高速度 . fetch()和使用foreach中的pdostatement的简单循环方法有区别吗?

当我启动这个PHP脚本时,查询需要5-10秒 . 所以这与表的设置方式无关,如果我需要索引 . 我有其他表返回100万行,我不知道什么是获取它们的最佳方法 . 如果需要,我可以提高PHP的memory_limit,所以对我来说最重要的是SPEED .

感谢任何帮助 .

3 回答

  • 0

    我不知道为什么,但使用fetch()方法代替并执行$ ins_val填充,如下所示:

    $ins_vals[] = $x;
    $ins_vals[] = $y;
    

    并使用beginTransaction和commit使我的脚本快速令人难以置信 . 现在加上我的100.000点只需要大约1分钟 .

    我认为通过PDOStatement循环的array_merge和“丑陋”都会减慢我的脚本速度 .

    为什么有人贬低了我的问题呢?因为我缺少知识,你在惩罚我吗?谢谢 .

  • 1

    好吧,我生成了一个类,我在其中设置了sql,然后使用方法调用将每行的值放入 . 每当它达到特定限制时,它就会启动一个事务,使用尽可能多的占位符来准备语句,然后使用包含所有值的数组执行它,然后提交 . 这似乎足够快,至少它不再变慢 . 由于某些原因,如丹尼尔所建议的那样,它更快地在平面结构中增加值 . 对我而言足够了 .

    有时将函数执行一步插入是有好处的,因为当函数返回时,函数中使用的所有内存都将被释放,因此您的内存使用率保持较低 .

  • 0

    缓慢与数据库相关的可能性不大,因为在 $dbh->query() 调用之后,查询结束并且结果行全部在内存中(它们不在PHP变量中,但是它们在pgsql模块中可以在内存中访问)水平) .

    更可能的罪魁祸首是 array_merge 操作 . 每次循环迭代时,数组都会变大,并且每次操作都会重新创建整个数组 .

    您可能想要改为:

    $ins_vals[] = [$row['x'], $row['y']];
    

    虽然个人而言,在关注速度时,我会使用更简单的扁平结构:

    $ins_vals[] = $x;
    $ins_vals[] = $y;
    

    另一个不相关的观点是它似乎构建了一个包含大量占位符的查询,而不是通常使用占位符的方式 . 要向服务器发送大量值,有效的方法是使用 COPY ,如果不是普通插入,可能使用临时表,然后是服务器端合并操作 .

相关问题