一年前公司用PHP开发的ERP,现在有些报表的查询速度已经由当年的2秒上升到50秒。有些朋友会说,数据量大了,用MySQL这种关系型数据库会慢啊,但是有点离谱了吧。一个Java选手对于PHP还是有点生疏,凑合看吧。
看代码片段:
/**
先说说这段代码干啥用的吧 只看表面意思 不深究到底要干啥
看到下面的 3日 7日 15日 30日 一般人都能猜到这是要做销量情况的报表
*/
$onelist = Db::query("");//查询3日内商品的销售数量
$twolist = Db::query("");//查询7日内商品的销售数量
$threelist = Db::query("");//查询15日内商品的销售数量
$fourlist = Db::query("");//查询30日内商品的销售数量
//下面这一段具体要干啥没仔细看
$onelist = arr_val_key($onelist,'goodscode');//三日
$twolist = arr_val_key($twolist,'goodscode');//七日
$threelist = arr_val_key($threelist,'goodscode');//15日
$fourlist = arr_val_key($fourlist,'goodscode');//15以上
$sanlist = $onelist;//三日
//从这看应该是字段去重的,因为 3 7 15 30查到的数据商品goodscode肯定有重复的
$qilist = array_diff_key($twolist,$onelist);//七日
$shiwulist = array_diff_key($threelist,$twolist);//15日
$shanglist = array_diff_key($fourlist,$threelist);//15以上
//到这里组合出一个数组来
$list = array_merge($sanlist,$qilist,$shiwulist,$shanglist);
$date = array(
array('count'=>0,'stime'=>strtotime ("-3 day"),'etime'=>strtotime ("-1 day")),
array('count'=>0,'stime'=>strtotime ("-7 day"),'etime'=>strtotime ("-1 day")),
array('count'=>0,'stime'=>strtotime ("-15 day"),'etime'=>strtotime ("-1 day")),
array('count'=>0,'stime'=>strtotime ("-30 day"),'etime'=>strtotime ("-1 day"))
);
foreach ($list as $k=>$v) {//根据组装得到的list数组再依次循环去查数据库,得到每个商品的数量。
$newdata = $date;
//第 1 次查数据库数量
$oneinfo = Db::query(" select ifnull(sum(goods_count*-1),0) goods_count ");
//第 2 次查数据库数量
$twoinfo = Db::query(" select ifnull(sum(goods_count*-1),0) goods_count ");
//第 3 次查数据库数量
$threeinfo = Db::query(" select ifnull(sum(goods_count*-1),0) goods_count ");
//第 4 次查数据库数量
$fourinfo = Db::query(" select ifnull(sum(goods_count*-1),0) goods_count ");
$newdata[0]['count'] = $oneinfo[0]['goods_count'];
$newdata[1]['count'] = $twoinfo[0]['goods_count'];
$newdata[2]['count'] = $threeinfo[0]['goods_count'];
$newdata[3]['count'] = $fourinfo[0]['goods_count'];
$list[$k]['stocklist'] = $newdata;
}
重点:
按上述代码的写法是 先根据3日 7日 15日 30日四种情况去查每种情况下的商品信息,取到了再组合去重得到一组商品数据集合(没搞懂为什么要这么取,这不是重点,不予深究),然后再根据数组循环查4种情况的销售数量。现在的问题是用这种凑数据的方法执行效率太低了,也片面的反映出来 这个小伙伴不愿意写SQL语句吧。
解决方法:
用SQL语句来处理,我们首先分析一下到底要干啥,搞明白了要干什么才能用一种合适的方法来处理事情。
这里提供两种思路,仅供参考。
1.采用字段 子查询的方法(伪代码)
select g.id,g.name,
(select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 3 and goods_id=g.id) '三日' ,
(select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 7 and goods_id=g.id) '七日' ,
(select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 15 and goods_id=g.id) '十五日' ,
(select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 30 and goods_id=g.id) '三十日'
from goods g
2.关联查询(伪代码) 将 三日。。。这些子查询当成一种结果集使用
select g.id,g.name,A.goods_count '三日',B.goods_count '七日',C.goods_count '十五日',D.goods_count '三十日'
from goods g
left join (
select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 3 and goods_id=g.id group by goods_id
)A on g.id=A.goods_id
left join (
select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 7 and goods_id=g.id group by goods_id
)B on g.id=B.goods_id
left join (
select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 15 and goods_id=g.id group by goods_id
)C on g.id=C.goods_id
left join (
select sum(goods_count) from order_detail where TO_DAYS(NOW()) - TO_DAYS(ctime) <= 30 and goods_id=g.id group by goods_id
)D on g.id=D.goods_id
三种方法比较,PHP循环调用查询需要56秒,第一种SQL语句需要10秒,第二种SQL语句需要2秒。我觉得2秒就可以忍受了
您更喜欢哪一种呢。欢迎留言交流。