0

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

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);
4

3 回答 3

2

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

$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)中。

结果数组是$hashkeys ( $data)

$data = array_keys( $hash );
print_r( $data );
于 2013-05-29T07:45:23.733 回答
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);

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

于 2013-05-29T07:33:56.110 回答
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]);
}
于 2013-05-29T07:45:24.773 回答