PDO无缓冲查询仍在等待,直到查询结果完成

时间:2017-01-18 12:08:43

标签: php mysql pdo

我有一个SQL查询可以返回很多结果(类似10k行),但是我不能使用SQL LIMIT参数,因为我不知道所需行的确切数量(在PHP中有一个特殊的分组) )。因此,计划是在我有足够的时间后停止获取行。

由于PDO通常以缓冲模式运行,它取出整个结果集并将其传递给PHP,因此我将PDO切换到无缓冲模式

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

现在我预计执行查询应该花费大约相同的时间,无论我通过什么LIMIT。所以基本上

$result = $pdo->query($query);
$count = 0;
while ($row = $result->fetch()) {
    ++$count;
    if ($count > 10) break;
}

应该在大约相同的时间执行

$query = 'SELECT * FROM myTable';

$query = 'SELECT * FROM myTable LIMIT 10';

然而,第一个需要8秒,而第二个需要立即执行。因此,看起来无缓冲的查询也会等到获取整个结果集 - 根据文档不应该这样。

有没有办法在PHP中使用PDO立即获取查询结果,一旦我有足够的结果就停止查询?

像“Sequel Pro SQL”这样的数据库应用程序可以做到这一点(我可以在1秒后点击取消并获得直到那时已经查询过的结果)所以它不是MySQL服务器的一般问题。

我可以通过选择一个非常高的LIMIT来解决问题,该LIMIT在我的分组后总是有足够的有效结果。但由于性能是一个问题,我只想查询真正需要的条目。请不要提出涉及MySQL分组的任何内容,这可怕的表现就是我们必须改变行为的原因。

2 个答案:

答案 0 :(得分:0)

  

现在我预计执行查询应该花费大约相同的时间,无论我通过什么LIMIT。所以基本上

这可能不完全正确。虽然您不会获得收到所有结果的开销,但他们都被查询(没有限制)!您确实可以将大多数结果保留在服务器上直到您需要它们,但据我所知,您的服务器实际上确实执行了整个查询。我不确定您的查询有多复杂,但这可能是问题吗?

例如,假设你有一个非常慢的连接(没有索引),但只想要前面的10个id,你的查询将根据索引获得10,然后只为那些10进行连接。这个'快点

但是,如果您实际上没有限制,但是要批量询问结果,则必须完成整个连接(慢!),然后您的结果集将以部分形式发布。

更快捷的方法可能是重复您的有限查询,直到您获得结果。我知道,这会增加开销,但可能会更快。唯一知道的方法就是测试。

作为对您评论的回复:来自the manual

  

无缓冲的MySQL查询执行查询,然后在数据仍在MySQL服务器上等待获取时返回资源。

所以它执行查询。完整的查询。因此,当我尝试在上面解释时,它不会像使用LIMIT 10的同一查询一样快,因为它不会执行部分查询!不同的数据库引擎这样做的事实并不意味着MySQL可以......

答案 1 :(得分:-1)

您是否尝试过使用prepare / execute代替query,并在休息后进行$stmt->closeCursor();来电?

$stmt = $dbh->prepare($query);
$stmt->execute();
$count = 0;
while ($row = $stmt->fetch()) {
    ++$count;
    if ($count > 10) break;
}
$stmt->closeCursor();