从MYSQL中阅读时减少PHP内存使用

jtjikinw  于 2023-10-15  发布在  PHP
关注(0)|答案(3)|浏览(91)

我必须从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
但是当我检查内存使用情况时,我得到了大约74 MB,为什么?
范例:

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

有没有一种方法可以加速/优化上述数组的创建?

  • PS:在mysql表中:type、cat和added是索引 *
u59ebvdq

u59ebvdq1#

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

  1. PHP和大多数内存占用可变的程序一样,将从一个小的分配开始,当它接近可用容量时,它将向操作系统请求更多的内存。这样做会产生执行开销,PHP不知道峰值内存使用量是多少,所以它会请求一个块。因此,当它愉快地运行时,它总是拥有比它使用的更多的内存。
    1.在MyQSL中,每个记录都具有相同的结构。所以它只需要存储一次属性名称。但PHP将其表示为一个或多个数组。每个记录元素还必须有记录结构的表示。
  2. PHP中的每个数据项都存储在一个称为ZVAL的结构中。这捆绑了大量的元数据。特别重要的是数据类型和引用计数(因此PHP知道何时可以丢弃该值)
    1.如果PHP只是简单地用名称、zval和数据填充内存,那么占用的空间会小得多。但是每次它想要检索一个值时,它都需要对数据进行线性搜索。这将需要大量的时间。它使用索引和哈希来加速变量的解引用。
    1.除了数据之外(实际上在考虑数据之前),PHP还需要将PHP源代码存储在内存中,并将人类可读的内容转换为更接近硬件理解的内容。上次我检查的时候,这平均是原始代码大小的3倍左右。
    有没有办法加快速度
    内存使用不会对性能产生太大影响,除非您的机器已经处于交换状态。但是,根据您没有告诉我们的内容,内存占用量很可能有显著减少的空间:假定存在阅读所有这些数据的某种原因,即,你想对数据进行某种转换,或者把它发送到PHP内存以外的地方。但我们不知道那是什么,所以不能建议。
ni65a41a

ni65a41a2#

如果你只能处理一次数据,那么在循环中进行处理。也就是说,甚至没有$array,只需处理$row,然后让$row被覆盖。
这可能只会保存74 MB的一半。肮脏的小秘密是,mysqli_query已经将所有14300行放入RAM。然后,您的代码在$array中创建另一个副本。有一种方法可以一次获取几行数据,但我推断这种技术的缺点比RAM的成本更糟糕。
与此同时,我同意@syncbean的回答(释义为“不是问题”)。我很久以前就知道,用自己的数组获取整个SELECT's结果并不是什么大事。但是,我仍然做了上面的“逐行消费”技术,因为我总是在考虑“速度和空间”。(我学会了编程 * 之前 * 机器运行在1 MHz和1 MB的RAM。

oprakyz7

oprakyz73#

根据所提供的信息,我认为一种方法是使用group_concat
你的台词,

$array[$row['cat']][$row['type']][] = $row;

告诉我你只关心把所有相关的type分组到cat。因此,您可以改为改革您的查询如下,然后在types列上explode,然后获得您想要的结果。

<?php

$res = mysqli_query( $con, "
           SELECT cat, group_concat(DISTINCT type  SEPARATOR ',') as types, other_columns
           FROM myTable
           group by cat
           ORDER BY type ASC, added DESC" );

while( $row = mysqli_fetch_assoc( $res ) ) { 
  foreach (explode(',', $row['types']) as $t) {
    $array[$row['cat']][$t] = $row;
  }
}

与14300相比,上面的操作将有助于减少行,因为我们是按cat分组的,我们可以再次使用explode来加快PHP端的进程。

相关问题