PDO PHP Postgres:缓慢获取数据

时间:2013-05-30 14:28:52

标签: php postgresql pdo fetch

我在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 :(得分:1)

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

array_merge操作的罪魁祸首。每次循环迭代时,数组都会变大,操作每次都会重新创建整个数组。

您可能想要改为:

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

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

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

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

答案 1 :(得分:0)

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

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

并使用beginTransaction和commit使我的脚本快速令人难以置信。 现在只需要1分钟就能增加我的100.000分。

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

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

答案 2 :(得分:0)

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

有时候让函数执行一步插入很有用,因为当函数返回时,函数中使用的所有内存都将被释放,因此你的内存使用率会保持很低。