2010-05-26 46 views
1

$ res包含大约488k行,整个循环需要61s!每个周期超过1.25ms!什么时候需要什么?为什么这个循环通过mysql结果集很慢? (每周期1.4ms)

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']; 
} 
+1

你需要加载所有这些结果到内存? – 2010-05-26 09:40:33

+0

61s中的488k行实际上是每次迭代0.125ms,所以只有3倍慢了30倍。我花了很长时间盯着这些数字,认为他们不是很对,因为我打扰到检查! :) – Chris 2010-05-26 10:23:31

回答

2

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

+0

我以为那只是因为我们是**懒惰** – 2010-05-26 09:39:04

+0

谢谢。没办法加速它?这不是一个Web应用程序,而是一个小型的PHP deamon与大量的数据混合。所以我不介意等待,但100%cpu的一分钟有点极端,结果集会增长10倍。 – pawpro 2010-05-26 09:39:47

+0

在数据库中做任何你可以做的事情。它会*总是*比你写的代码更快。而且你可以获得更少的代码,你需要编写的额外奖励。 – 2010-05-26 09:40:55

0

可疑该什么把所有的时间是4维阵列,其中所述尺寸中的一些(或所有?)正在从字符串字段键控,本身不必从$row提取这些值持续访问...

我建议你认真考虑:

  1. 是否需要所有的内存
  2. 如果是这样,最好的数据结构将是怎样的最佳接入
1

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['..']; 
} 

这样,你只是做数组查询一次,而不是反反复复,并可能会显着减少运行时间。尽管如此,坚持一个数组中的许多事情不会很快。

从长远来看,您最好的选择是将数据保留在数据库中,并且只在需要时才抓取位(或者让数据库为您付出沉重的代价,如果您尝试总结/平均/不管)。

+0

谢谢。我确实需要高速数据库中的随机数据,所以我希望不必对数据库造成压力,因为我可能会连续发送大量数据以高于500 q/s的速率处理,而且目前我无法负担得起数据库上的不可预知的负载。我会玩它更糟糕的情况下,我会尝试memcached :) – pawpro 2010-05-26 09:56:36

0

这个什么:

$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']; 
} 
+0

我看到你在哪里用这个......不错,我会给memcached一个镜头:) – pawpro 2010-05-26 10:10:18

+0

@pawpro:memcached不会加快行为索引到一个数组本身。由于您在循环中执行了许多平等查找,因此即使基于memcached的解决方案也能从此方法中受益。 – Tomalak 2010-05-26 10:30:29

+0

我做了重新调整,但是我希望只有<1%的数据在常规使用中会被“按需提供”。因此,使用memcached缓存它是合理的(数据库查询缓存会在表更改时导致高缓存缺失率 - 但不会影响现有数据) – pawpro 2010-05-26 10:48:20