我一直觉得 PHP/MySQL 缓冲查询和无缓冲查询之间的区别简单来说是缓冲(默认)将所有数据加载到结果集变量中,然后您可以开始使用它们,而无缓冲加载一行一次。
假设你跑了SELECT * FROM sometable
,然后做了$result = $db->query($query);
,$result
将包含所有行和补充信息,例如行数。因此,如果您在 100MB 的数据库上执行此操作,那么如果那里没有索引,您预计$result
会占用约 100MB)。
但是,我遇到了这个SO 溢出问题,其中提到了缓冲查询:
[The] 结果将包含一些依赖于实现的行缓冲区。它可能是 100 行或更多或更少。为每一行返回所有列;当您最终获取更多行时,客户端将向服务器请求更多行。这可能是客户端用完的时候,也可能是抢先完成的。
是这样吗,真的还有一些缓冲吗?如果是这样的话,我们一般不需要担心 PHP 在处理大型结果集时会耗尽内存吗?这很奇怪,因为我一直在 40MB 的测试表上运行一些测试缓冲查询,而 PHP 总是报告大约 5MB 的峰值内存使用量。
最后,根据经验,你什么时候选择无缓冲而不是缓冲?你能举个例子吗?
谢谢。
(顺便说一句,我正在使用 MySQLi。我假设主体是相同的)。
编辑:我现在已经阅读了更多内容,并且更加困惑。在http://php.net/manual/en/mysqli.quickstart.statements.php它说
On After 语句的执行结果可以立即检索到由客户端缓冲或逐行读取。客户端结果集缓冲允许服务器尽早释放与语句结果相关的资源。一般来说,客户端消耗结果集的速度很慢。因此,建议使用缓冲结果集。mysqli_query() 结合了语句执行和结果集缓冲。
PHP 应用程序可以在缓冲结果中自由导航。导航速度很快,因为结果集保存在客户端内存中。请记住,按客户端扩展通常比扩展服务器更容易。
在http://php.net/manual/en/mysqli-result.fetch-all.php它说:
由于 mysqli_fetch_all() 在单个步骤中将所有行作为数组返回,因此它可能比一些类似的函数(例如 mysqli_fetch_array())消耗更多的内存,后者一次只从结果集中返回一行。此外,如果您需要对结果集进行迭代,您将需要一个循环结构来进一步影响性能。由于这些原因,mysqli_fetch_all() 应该只用于那些将获取的结果集发送到另一层进行处理的情况。
这似乎有些矛盾。“客户端结果集缓冲”和“消费结果集”有什么区别?一个说它们保存在客户端内存中,另一个说逐行读取。如果整个事情都缓冲到 PHP,为什么最后一句话说如果你在一个步骤中将所有行作为数组返回,它可能会消耗更多内存?