在 PHP (PDO) 中了解 MySQL 的内存使用情况
Posted
技术标签:
【中文标题】在 PHP (PDO) 中了解 MySQL 的内存使用情况【英文标题】:Understanding memory usage of MySQL result in PHP (PDO) 【发布时间】:2016-11-27 21:51:29 【问题描述】:我试图了解为什么单个 PDO 结果的内存使用率如此之高。以下是有关查询/结果的一些注意事项:
我正在从单个表中提取单个VARCHAR(6)
列
结果少于 30K 行
在 php 中获取此结果使用 ~12MB 内存(来源:memory_get_usage
)
如果我 json_encode
将结果转储到文件中,则实际数据(文本形式)只有 ~1MB
使用 PHP7、mysql 5.7,部署在 Ubuntu 14.04 上。
我的问题是,11MB 的膨胀究竟是从哪里来的?如果文本形式的实际数据只有 1MB 左右,那么 11MB 似乎只是在 PHP 中解析数据的开销很大。是否有一个原因?我错过了什么吗?
编辑:
为了澄清,我正在寻找关于为什么存在膨胀的技术解释,而不是解决该问题的方法。
【问题讨论】:
【参考方案1】:好的,感谢 Ollie Jones 的回答,我意识到我一直在错误的地方寻找我的信息。这不是 PDO 内存使用问题,而是 PHP 存储其数组的方式的问题。 (也许问题不是正确的词,它就是这样)
经过一番挖掘,我发现这篇非常有用的文章对 PHP 如何为数组元素分配内存进行了详细的分析:
https://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html
剧透警告,它为每个元素使用大量内存。显然它在 PHP7 中变得更好了。文章指出,对于一个简单的整数数组(在 PHP5 中)元素,它将使用大约 18 倍于整数本身大小的内存。由于我看到关联字符串数据增加了大约 12*,我说这确实是对 PHP5 的巨大改进。
根据文章,正在为以下内容分配内存:
zvalue_value
union,这与 PHP 允许的弱类型转换有关
类型存储和垃圾收集数据
Zend 内存管理器分配
哈希表桶
如果您也对此感兴趣,我强烈建议您阅读那篇文章,它是快速阅读并且包含大量重要信息。
再次感谢 Ollie Jones 为我指明了正确的方向。
【讨论】:
【参考方案2】:如果没有看到您的具体代码,很难给出具体答案。话虽如此,像数组这样的 PHP 数据结构是关联的。 PHP 设计者有意权衡使用额外的 RAM 来节省数组访问时间。
您可以通过多种方式节省内存。一方面,您可以将结果集的每一行作为数字而不是关联数组获取。读这个。 http://php.net/manual/en/mysqli-result.fetch-array.php
另外,PHP 会一次性读取结果集中的所有行,除非您告诉它不要这样做。这种 slurp 操作会消耗大量 RAM。如果您打算一次处理一行大型结果集,则不需要它。您需要一个无缓冲查询来做到这一点。阅读:http://php.net/manual/en/mysqlinfo.concepts.buffering.php
【讨论】:
感谢您的回复。我可以展示我的代码,但它只不过是使用 fetchAll 执行的通用 PDO 查询。我敢肯定,联想会增加一点内存,但我无法想象它会占用 11MB 的数据。我过去使用过无缓冲查询,这确实解决了这个问题,它只是没有回答关于额外 11M 膨胀来自哪里的问题。 PHP 是开源的。如果你好奇的话,你可以看看它是如何处理数组的。我怀疑它使用哈希表来维护您的大型数组,并且可能将它们分配得足够稀疏以避免过多的哈希冲突。甚至 PHP 中的数字数组也是关联的。请记住,PHP 是为网页渲染而设计的,因此大数组案例并不是其目标用途的中心。 Java 和 C# 有更高效的集合类。 github.com/php/php-src以上是关于在 PHP (PDO) 中了解 MySQL 的内存使用情况的主要内容,如果未能解决你的问题,请参考以下文章