2013-06-26 88 views
15

我总是觉得PHP/MySQL缓冲和非缓冲查询之间的区别是,缓冲(默认)将所有数据加载到结果集变量中和然后您可以开始使用它们,而不缓冲一次加载一行。PHP + MySQL:缓冲和非缓冲查询之间的区别

假设你跑SELECT * FROM sometable,然后做$result = $db->query($query);,$result将包含所有的行和补充信息,如行数。所以如果你在一个100MB的数据库上做了这个工作,你会发现$result在没有索引的情况下占用了大约100MB)。

不过,我碰到这个SO overflow question其中一部分表示缓冲查询:

[的]结果将包含行的一些缓冲区实现有关。它可能是100行或更少或更少。所有列都为每行返回;当您最终获取更多行时,客户端会向服务器请求更多行。这可能是客户用完或可能会抢先完成的情况。

这是对的吗,还真有一些缓冲吗?如果是这样的话,当处理大型结果集时,我们通常不需要担心PHP内存不足吗?这很奇怪,因为我一直在40MB测试表上运行一些测试缓冲查询,而PHP总是报告大约5MB的峰值内存使用量。

最后,作为一个经验法则,你什么时候选择无缓冲缓冲?你能举个例子吗?

谢谢。

(我正在使用MySQLi,我假设主体是一样的)。

编辑:我现在读了更多,我更加困惑。在http://php.net/manual/en/mysqli.quickstart.statements.php它说

在语句执行结果可以立即被检索到客户端缓冲或逐行读取。客户端结果集缓冲允许服务器尽早释放与语句结果相关的资源。一般来说,客户端是耗时较慢的结果集。因此,建议使用缓冲结果集。 mysqli_query()结合语句执行和结果集缓冲。

PHP应用程序可以通过缓冲结果自由导航。导航速度很快,因为结果集保存在客户端内存中。请记住,客户端扩展通常比扩展服务器更容易。

而就http://php.net/manual/en/mysqli-result.fetch-all.php它说:

作为mysqli_fetch_all()返回的所有行作为在单个步骤中的阵列,其可以消耗比一些类似的功能,如mysqli_fetch_array(),多个存储器,其从结果集中一次只返回一行。此外,如果您需要遍历结果集,则需要一个循环构造,这会进一步影响性能。由于这些原因,mysqli_fetch_all()应该仅用于那些将获取的结果集发送到另一个层进行处理的情况。

这似乎有些矛盾。“客户端结果集缓冲”和“消费结果集”之间有什么区别?一个说他们被关在客户端内存中,另一个则说是逐行读取。如果整个事情被缓冲到PHP为什么最后一句话说如果你在一个步骤中将所有行作为数组返回,它可能会消耗更多的内存?

+0

缓冲处理内部到SQL Server而不是PHP – Dave

+0

这是否涉及到我上面的编辑?如果你能在你的回答中向我解释,我会接受它。谢谢。 – texelate

+1

它不应该被称为缓冲tbh它应该被称为结果缓存。 PHP将保存整个结果对象的一小部分,然后它必须从MySQL中取出其余部分。我想不出任何人在php做客户端的实例,除非这意味着PHP作为MySQL的客户端。 Mysql会进行内部查询缓冲和缓存以加快查找速度,而不必进行全表读取等操作。基本上,尽管在标准的mysql使用情况下,您不需要担心它,只需让它将它自己排序即可。 – Dave

回答

14

参见:http://php.net/manual/en/mysqlinfo.concepts.buffering.php

无缓冲的MySQL查询,执行查询,然后返回一个资源 而数据仍然在MySQL服务器上等待被取出。 这在PHP端使用较少的内存,但可以增加服务器上的负载 。除非完整的结果集是从服务器取得的否 进一步的查询可以通过同一连接发送。无缓冲 查询也可以称为“使用结果”。

以下这些特性应该在您希望只有有限的结果集或需要在读取所有行之前知道返回的行数时使用缓冲查询。当你期待更大的结果时,应该使用非缓冲模式。

缓冲查询是默认的。

无缓冲举例:

<?php 
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); 
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); 

if ($uresult) { 
    while ($row = $uresult->fetch_assoc()) { 
     echo $row['Name'] . PHP_EOL; 
    } 
} 
$uresult->close(); 
?> 

希望这有助于

+0

好点。实际上,通过使用free_result()放弃结果资源,您可以在同一连接上使用多个准备好的语句/查询。但是,这会阻止您从此结果集中获取更多的元组/行。 –