从 MYSQL 读取时减少 PHP 内存使用量

Reducing PHP memory usage while reading from MYSQL

提问人:ipel 提问时间:10/13/2023 更新时间:10/14/2023 访问量:90

问:

我必须从 mysql 表中读取所有行,然后将所有行存储在 PHP 数组中。

例:

$res = mysqli_query( $con, "SELECT * FROM myTable WHERE 1 ORDER BY type ASC, added DESC" );
while( $row = mysqli_fetch_assoc( $res ) ) { 
  $array[$row['cat']][$row['type']][] = $row; 
}

该表有 14300 行,大小为 10.8MB

但是当我检查内存使用情况时,我得到大约 74MB,为什么?

例:

echo memory_get_usage(); // return 74.6MB
echo memory_get_peak_usage(); // return 74.6MB

有没有办法加快/优化上述数组的创建?

PS:在mysql表中:type,cat和added是索引

php mysql 数组选择

评论

0赞 Nigel Ren 10/13/2023
有没有办法编码,以便以块的形式处理数据,因为这不仅与数据的大小有关,还与处理数据所需的时间有关。
4赞 Nico Haase 10/13/2023
脚本中是否需要所有 14300 行?您是否已经在为分配 74 MB 的内存而苦苦挣扎(这并不多),或者您是否担心随着行数的增加,内存会变得更大?

答:

4赞 symcbean 10/13/2023 #1

当我检查内存使用情况时,我得到大约 74MB,为什么?

  1. PHP与大多数具有可变内存占用的程序一样,将从少量分配开始,当它接近可用容量时,它将要求操作系统提供更多内存。这会产生执行成本开销,PHP 不知道峰值内存使用量是多少,因此它要求一个块。因此,当它愉快地运行时,它的内存总是比它使用的内存多。

  2. 在 MyQSL 中,每条记录都具有相同的结构。因此,它只需要存储一次属性名称。但是 PHP 将其表示为一个或多个数组。每个记录元素还必须具有记录结构的表示形式。

  3. PHP 中的每个数据项都存储在称为 ZVAL 的结构中。这捆绑了大量元数据。特别重要的是数据类型和引用计数(因此PHP知道何时可以丢弃该值)

  4. 如果 PHP 只是用名称、zvals 和数据填满内存,那么占用空间会小得多。但是,每次它想要检索一个值时,它都需要对数据进行线性搜索。这将花费大量的时间。它使用索引和哈希来加速变量的取消引用。

  5. 除了数据之外(实际上在考虑数据之前),PHP 还需要将 PHP 源代码存储在内存中,并将人类可读的东西转换为更接近硬件理解的内容。我上次检查时,平均大小约为原始代码大小的 3 倍。

有没有办法加快速度

除非您的计算机已经处于交换状态,否则内存使用率不会对性能产生太大影响。但是,根据您没有告诉我们的内容,内存占用很可能有显着减少的余地:大概有一些原因需要读取所有这些数据 - 即您想对数据执行某种转换或将其发送到 PHP 内存以外的地方。但我们不知道那是什么,所以不能建议。

2赞 Rick James 10/14/2023 #2

如果只能处理一次数据,请在循环中执行处理。也就是说,甚至没有,只需处理然后被覆盖。$array$row$row

这可能只节省了 74MB 的一半。肮脏的小秘密是,它已经将所有 14300 行带入 RAM。然后,您的代码会在 中复制所有内容。有一种方法可以一次获取几行数据,但我推断该技术的缺点比 RAM 的成本更糟糕。mysqli_query$array

同时,我确实同意@syncbean的回答(套用“不是问题”)。我很久以前就知道,获取我自己的数组的全部结果并不是什么大不了的事情。但是,我仍然采用上述“逐行消费”技术,因为我总是在考虑“速度和空间”。(在机器以 1MHz 的速度运行并拥有 1MB 的 RAM 之前,我学会了编程。SELECT's

评论

0赞 Wilson Hauck 10/26/2023
里克,很好的建议。谢谢。