在PHP中独特地组合数千个数组的最快方法

时间:2013-05-29 07:28:10

标签: php arrays

我从数据库中获取数据。每个结果看起来都像这样

ASDF-1234-JKL-F1-STUFF

有50,000个结果。每个人都在爆炸

$exploded = explode('-',$dash_delimited_datum);

// $exploded = array('ASDF','1234','JKL','F1','STUFF');

我试过了:

$data = array();

while($row = mysql_fetch_array($result) ){
    $i++;
    if($i > 99999) {
        break;
    }
    $data = array_merge($data,explode('-',$row[0]));
}

但是用它来点击服务器超时5分钟。

这根本不起作用:

while($row = mysql_fetch_array($result) ){
    $i++;
    if($i > 99999) {
        break;
    }
    $data_parts = explode('-',$row[0]);
    foreach($data_parts as $value) {
        $data = array_push(($data,$value);
    }
}

出乎意料的是,这种情况很有效,“仅”9秒,但我想知道我是否可以让它更快:

while($row = mysql_fetch_array($result) ){
    $i++;
    if($i > 99999) {
        break;
    }
    $data = array_unique(array_merge($data,explode('-',$row[0])));
}
编辑:我提出了一个我认为最好的解决方案,在800毫秒 请注意,我使用“闭包”(匿名函数)来删除数字键,我认为这是一个拖动速度。但实际上,删除它会导致脚本在30秒时超时。

$data=array();
while($row = mysql_fetch_array($result) ){
    $i++;
    if($i > 99999) {
        break;
    }
    $data_parts = array_flip(array_filter(explode('-',$row[0]),
    function($value) {
        if(is_numeric($value)) {
                return false;
        } else return true;
    }));

    $data = array_merge($data,$data_parts);
}
$data = array_keys($data);
sort($data);

结论:

每个快速回答都使用涉及数组键的技巧,而不是值。我的最佳答案与下面两个非常快速的答案之间的区别似乎是他们在foreach内使用while loop来直接将值分配给主$data数组。 PHP 函数调用本来就很昂贵,这个例子似乎证明它们确实是。两个最佳答案都给了我300毫秒以下的结果。我最好的答案只有在我过滤掉数值时才能快速运行,否则会遇到30秒的服务器超时。

所以,我想如果您正在处理大量数据,请尽可能使用构造而不是函数

注意(是的,我知道他们已被弃用)mysql函数 一个答案建议我使用mysql_fetch_assoc而不是mysql_fetch_array。实际上,mysql_fetch_row应该是“最快的”,但是这个数据集的页面加载速度完全没有差异(大约48,000个结果)。我也尝试过使用mysql_result。 PHP文档说它在检索多行时速度较慢,而且速度要慢得多。

加载时间为6.27秒,相似结构的最佳答案约为0.27秒(270毫秒)。

$i=0;
while($data_parts = explode('-',mysql_result($result,$i,0)) ){
    $i++;
    if($i > 99999) {
        break;
    }
    foreach($data_parts as $value) {
        $data[$value] = 1;
    }
}
$data = array_keys($data);

3 个答案:

答案 0 :(得分:2)

为了加快这个过程,而不是使用昂贵的函数来处理数组,使用关联数组( hash )来确保唯一值应该有更快的速度

$i = 0;
$hash = array();

while($row = mysql_fetch_array($result)) {
    $i++;
    if($i > 99999) {
        break;
    }
    foreach (explode('-', $row[0]) as $s) {
        $hash[ $s ] = 1;
    }
}

这样,所有字符串唯一存储在关联数组中(称为 hash )。

生成的数组是$hash个键($data

$data = array_keys( $hash );
print_r( $data );

答案 1 :(得分:1)

这个怎么样(我删除了你的计数器,但如果必要,你可以加回来):

$data = array();
$i = 0;

while($row = mysql_fetch_array($result) )
{
    $data_parts = explode('-',$row[0]);

    foreach($data_parts as $value)
    {
        if (!isset($data[$value]))
            $data[$value] = $i++;
    }
}

$data = array_flip($data);

我无法真正在我的计算机上进行基准测试,所以如果它比你的实现慢,请告诉我!

答案 2 :(得分:0)

尝试使用mysql_fetch_assoc而不是mysql_fetch_array。 mysql_fetch_array返回数字和关联索引(有效地使数组的大小加倍)。另外,尝试在while循环中使用尽可能少的函数。例如,如果迭代50,000个元素,并且在每次迭代中有3个函数调用,则会调用150,000次函数。

另外,为什么在将结果传递给循环之前不要删除重复项?

SELECT someField 
FROM someTable 
GROUP BY someField 
HAVING COUNT(someField)>0

运行后,运行循环

$data = array();

while($row = mysql_fetch_assoc($result) ){
    $i++;
    if($i > 99999) {
        break;
    }

    $data[] = explode('-',$row[0]);
}