针对 80k 行的 PHP 数组优化


PHP array optimization for 80k rows

我需要帮助来找到克服memory_limit的解决方法。我的限制是 128MB,从数据库中我得到了大约 80k 行,脚本在 66k 处停止。感谢您的帮助。

法典:

$posibilities = [];
    foreach ($result as $item) {
            $domainWord = str_replace("." . $item->tld, "", $item->address);
            for ($i = 0; $i + 2 < strlen($domainWord); $i++) {
                $tri = $domainWord[$i] . $domainWord[$i + 1] . $domainWord[$i + 2];

                if (array_key_exists($tri, $possibilities)) {
                    $possibilities[$tri] += 1;
                } else {
                    $possibilities[$tri] = 1;
                }
            }
        }

考虑到您的算法,您的瓶颈很可能不是数据库查询,而是您正在构建的$possibilities数组。

如果我正确阅读了您的代码,您会从数据库中获得域名列表。从每个域名中,您首先从最后剥离顶级域名。

然后,从结果字符串的左到右逐个字符地移动,并从该字符串中收集字符的三元组,如下所示:

example.com => ['exa', 'xam', 'amp', 'mpl', 'ple']

您将这些三元组存储在数组的keys中,这是个好主意,并且还可以对它们进行计数,这对内存消耗没有任何影响。然而,我的猜测是,可能的三元组的绝对数量,即 26 个字母和 10 位数字是 36^3 = 46656 种可能性,每个可能性只需要 3 个字节,仅用于数组内的,不知道周围有多少样板代码,从内存限制中占用了很多。

可能有人会告诉你 PHP 如何使用内存及其数据库游标,我不知道,但你可以做一个技巧来分析你的内存消耗。

拨打电话memory-get-usage

  • 在每次迭代之前和之后,因此您将知道每次光标前进浪费了多少内存,
  • 每次添加到$possibilities之前和之后。

并立即打印它们。因此,您将能够运行代码并实时查看内存的使用内容和严重程度。

此外,尝试在每次迭代后unset $item。它实际上可能会有所帮助。

了解您用于获取迭代器的特定数据库访问库$result将有很大帮助。

鉴于您提供的微小(非常无用(的代码片段,我想为您提供一个MySQL答案,但我不确定您是否使用MySQL?

但- 优化您的餐桌。

  • 使用EXPLAIN来优化您的查询。重写查询,将尽可能多的逻辑放在查询中,而不是放在 PHP 代码中。编辑:如果您使用的是MySQL,请在SELECT关键字之前加上EXPLAIN,结果将显示您给MySQL的查询如何变成结果的实际解释。

  • 不要使用 PHP strlen 函数,因为这是内存效率低下的 - 相反,您可以通过将字符串视为一组数组值来进行比较,因此:

    for ($i = 0; !empty($domainWord[$i+2]); $i++) {

  • 在你的MySQL中(如果你正在使用的话(,然后添加一个LIMIT子句,将查询分成3或4个块,比如每个块25k行,这将舒适地适合你66k行的最大操作容量。布尔基有个好主意。

在每个块结束时清理所有字符串并重新启动,设置为循环

$z = 0;
 while ($z < 4){
///do grab of data from database. Preserve only your output 
$z++;
}

但可能比这些更重要的是在您的问题中提供足够的细节!!- 您想获得什么数据?- 你把数据存储在什么地方?- 查找数据的标准是什么?

这些答案将帮助比我知识渊博的人向您展示如何正确优化数据库。