【问题标题】:Why is this loop over mysql resultset slow? (1.4ms per cycle)为什么这个循环在 mysql 结果集上很慢? (每个周期 1.4 毫秒)
【发布时间】:2010-05-26 09:34:07
【问题描述】:

$res 包含大约 488k 行,整个循环需要 61 秒!每个周期超过 1.25 毫秒!这么多时间是怎么回事?

while($row = $res->fetch_assoc())
{
    $clist[$row['upload_id']][$row['dialcode_id']][$row['carrier_id']]['std'] = $row['cost_std'];
    $clist[$row['upload_id']][$row['dialcode_id']][$row['carrier_id']]['ecn'] = $row['cost_ecn'];
    $clist[$row['upload_id']][$row['dialcode_id']][$row['carrier_id']]['wnd'] = $row['cost_wnd'];
    $dialcode_destination[$row['upload_id']][$row['carrier_id']][$row['dialcode_id']]['other_destination'] = $row['destination_id'];
    $dialcode_destination[$row['upload_id']][$row['carrier_id']][$row['dialcode_id']]['carrier_destination'] = $row['carrier_destination_id'];
}

现在 10 行的结果集、更小的数组和性能提高了 30 倍 (0.041ms) 不是最快的,而是更好。

while($row = $res->fetch_assoc())
{
    $customer[$row['id']]['name'] = $row['name'];
    $customer[$row['id']]['code'] = $row['customer'];
}

【问题讨论】:

  • 您需要将所有这些结果加载到内存中吗?
  • 488k 行在 61 秒内实际上是每次迭代 0.125 毫秒,因此只慢了 3 倍而不是 30 倍。我花了 方式 太长时间盯着那些数字认为它们不正确在我懒得检查之前! :)

标签: php mysql loops resultset


【解决方案1】:

大数组需要更多时间来分配内存和处理。 这就是为什么我们总是要求数据库完成所有工作并返回 10 行作为最终结果。

【讨论】:

  • 我以为那只是因为我们
  • 谢谢。没有办法加速吗?它不是一个网络应用程序,而是一个处理大量数据的小型 php 守护程序。所以我不介意等待,但 100% cpu 的一分钟有点极端,结果集至少会增长 10 倍。
  • 在数据库中尽你所能。它会总是比您编写的代码更快。并且您会获得额外的好处,即您需要编写的代码更少。
  • IE从你所说的可以推断,获得所需的 30 倍提升的方法是将数组分解为更小的数组......
  • @pawpro 根据我们所说,您必须使用数据库来对这些数据进行计算
【解决方案2】:

488k 是很多行,这意味着很多数据。插入数组的项目越多,分配的内存就越多,查找元素所需的时间就越长。

当您执行几乎一百万次相同的代码时,值得优化数组访问:

... {
  $myclist =& $clist[$row['upload_id']][$row['dialcode_id']][$row['carrier_id']];
  $myclist['std'] = $row['..'];
  $myclist['ecn'] = $row['..'];
  ...
  $dest =& $dialcode_destination[$row['upload_id']][$row['carrier_id']][$row['dialcode_id']];
  $dest['..'] = $row['..'];
  $dest['..'] = $row['..'];
}

这样,您只需进行一次数组查找而不是重复进行一次,并且可能会显着减少运行时间。不过,无论如何,将这么多东西放在一个数组中并不会很快。

从长远来看,最好的办法是将数据保留在数据库中,只在需要时才获取数据(或者如果您想求和/平均,则让数据库为您完成繁重的工作/随便)。

【讨论】:

  • 谢谢。我确实需要以高速率从数据库中获取随机数据,因此我希望不必对数据库施加压力,因为我可能会以高于 500 q/s 的速率连续处理大量数据,而我目前无法承受这样的负担数据库上不可预测的负载。我会在最坏的情况下使用它,我会尝试 memcached :)
【解决方案3】:

怀疑一直在持续访问 4 维数组,其中一些(或全部?)维度是从字符串字段键入的,这些值本身必须提取自$row...

我建议你认真重新考虑:

  1. 您是否需要内存中的所有内容
  2. 如果是这样,最佳访问的最佳数据结构是什么

【讨论】:

    【解决方案4】:

    这个呢:

    $cache = array();
    while($row = $res->fetch_assoc())
    {
        $key = $row['upload_id']."\n".$row['dialcode_id']."\n".$row['carrier_id'];
        $key1 = "1\n$key";
        if (!array_key_exists($key1, $cache))
          $cache[$key1] = &$clist[$row['upload_id']][$row['dialcode_id']][$row['carrier_id']];
    
        $ref = &$cache[$key1];
        $ref['std'] = $row['cost_std'];
        $ref['ecn'] = $row['cost_ecn'];
        $ref['wnd'] = $row['cost_wnd'];
    
        $key2 = "2\n$key";
        if (!array_key_exists($key2, $cache))
          $cache[$key2] = &$dialcode_destination[$row['upload_id']][$row['carrier_id']][$row['dialcode_id']]
    
        $ref = &$cache[$key2];
        $ref['other_destination']   = $row['destination_id'];
        $ref['carrier_destination'] = $row['carrier_destination_id'];
    }
    

    【讨论】:

    • 我知道你在做什么......很好,我先试试 memcached :)
    • @pawpro:memcached 不会加快对数组本身的索引操作。由于您在一个循环中执行许多相等的查找,因此即使是基于 memcached 的解决方案也将从这种方法中受益。
    • 我确实很喜欢,但我预计只有
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多