php循环处理6万条数据性能优化问题

何建城 2016-02-01 09:55:31
如下代码,这是服务器上的一个脚本文件的。变量$productList里取出的表erp_products_data里的数据,有6万多条,也就是我的foreach循环要跑6万多次,而循环里面,还要处理3个查询sql,1个更新sql,循环万总计跑了24万多sql才结束。这样的结果是慢。我自己的思路是把sql拆分处理,因为一次性处理6万多数据非常慢的话,对内存是一个极大的影响,这问题可能还有其他优化方案,所以问问各位老哥们优化的方法。
注:1. foreach里面的查询无法取出一次性处理,复杂性会更大,性能不会太好
2. 这是一个全表扫的sql,需要计算每一个行的某个字段的值,每天都需要计算


$productList = $productsManage->getAllActiveProductList($fields, $params);
//print_r($productList);exit;
if (empty($productList)){
die('没有获取到产品信息');
}

$table = "erp_products_data";
$i = 0;
//开始循环来计算吧
foreach ($productList as $pro){

//SKU
$sku = trim($pro['products_sku']);
$warehouse = $pro['product_warehouse_id'];
$id = $pro['products_id'];

//计算利润率
$avgProfitRate = $getTotals->getSkuFiveAverage($sku);

//计算60天退款次数
$skuMoneybackCount = getSkuMoneybackCount($sku);

//计算各仓库的60天销量
$sold_60 = getSalesTotalInSalesRecordMinDays($sku, 60 ,$v['product_warehouse_id']);

$data = array();
$data['sold_60'] = $sold_60;
$data['backMoney_60'] = $skuMoneybackCount;
$data['profitRate_15'] = $avgProfitRate;

$where = " products_id=".$id;
$doSql->update($table, $data, $where);
if($i>100){
$end_time = microtime(true);
$ret_time = $end_time - $start_time ;
echo "Code execution time is ".$ret_time." second";
echo 'the end...';
exit;
}
$i++;
}
...全文
4642 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
智商众筹 2016-02-16
  • 打赏
  • 举报
回复
触发式好一些,有人看的时候再计算,今天计算过的不用再次计算 但如果你想搞排名就不行了,把6W多条数据拆开来一点点处理
傲雪星枫 2016-02-15
  • 打赏
  • 举报
回复
1.看看查询的,对查询字段都加了索引 2.更新可以把多条更新语句先保存,然后批量更新,这样可以减少锁表开锁时间 3.相同的product估计数据是一样的,可以先把所有product放入cache,使用时直接从cache读取,减少连接数据库操作。 4.更新涉及锁表,所以多线程都是需要等待的。
xuzuning 2016-02-15
  • 打赏
  • 举报
回复
如果没有大量 I/O 操作,多线程要比单线程还慢!
何建城 2016-02-15
  • 打赏
  • 举报
回复
目前是crontab开了4个线程跑的
码无边 2016-02-02
  • 打赏
  • 举报
回复
1.如果数据量很大, 可以用计划任务去跑,如果实时性要求不是很高。 2.开启多个线程去处理数据,这样在速度上有提高。
何建城 2016-02-01
  • 打赏
  • 举报
回复
@xuzuning 目前来看 版主的考虑是对的 这块可以改为批量更改就能解决 @jam00这位朋友的也是很好的 监听触发 异步队列执行,可以代码上来监听,也可以写个触发器监听。业务上来看,这块触发的地方有点多,代码监听可能不太适合,触发器监听应该会比较好 不过这块最好不写触发器 所以我考虑版主的批量进行试一下 性能应该会好很多
xuzuning 2016-02-01
  • 打赏
  • 举报
回复
这三个量在计算时只传递了简单的参数,而这三个量都与历史数据有关(都是统计值) 你不去考究他们的算法,就想当然的说 性能还可以。是很不严肃的
果酱很好吃 2016-02-01
  • 打赏
  • 举报
回复
提供两个方案吧 1、改为触发式的更新,不用每天都集中在同一个时间段统计。若是这个产品被读取出来显示了(不管是列表还是详情之类的,看你业务需求),并且今天还没有更新过(可在 erp_products_data 表设置一个字段来标识),就执行统计更新,最好是异步 2、改为异步并发统计,就像你设置crontab 一样,只是这是代码层上的,一个分发页面,一个执行页面,执行页面接收来自分发页面的参数,从哪里开始执行统计,可以异步发起多个执行请求(10个,20个,随你)
何建城 2016-02-01
  • 打赏
  • 举报
回复
问题的话按理来说肯定是出现在这几个变量的计算,所以我本地测试了一下,跑100条数据的时候耗时是 6.9323971271515,这性能也不想说了,代码是前人写的。也就是1000条需要70秒,10000条需要1个小时这样 4个线程的话也是这样计算 但是问题是 我本地测试没有问题 虽然会慢一点 线上服务器发生了一个问题 死锁 这搞得比较纠结 所以这块得急需优化一下 但是问题是 $data['sold_60'] = $sold_60; $data['backMoney_60'] = $skuMoneybackCount; $data['profitRate_15'] = $avgProfitRate; 这三个的计算消耗的速度性能还可以..
xuzuning 2016-02-01
  • 打赏
  • 举报
回复
$data['sold_60'] = $sold_60; $data['backMoney_60'] = $skuMoneybackCount; $data['profitRate_15'] = $avgProfitRate; 这三个量是如何计算的? 瓶颈应该在这里
何建城 2016-02-01
  • 打赏
  • 举报
回复
目前我是把他拆分开 跑4次 性能还是不行
何建城 2016-02-01
  • 打赏
  • 举报
回复

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧