关于 eloquent 查询数据库表的问题

做一个有36W条数据的数据库table,
$customerHistory = SO::where('id'$id)->get();
用eloquent 去搜索 获得大约2W条数据,用get()获得。

在localhost 上用的时候很OK,
但是上传了 shared host 总是会报错 internal error 500

但是加了$customerHistory = SO::where('id'$id)->limit(5000)->get() 就好;

但是加5W 又报错

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 16
leo

目测是内存溢出了,把PHP的内存限制改大一点

7年前 评论
lijinma

第一:这么做不太合理,一次取这么多数据不对,建议你考虑分页。
第二:出现500的错误,想办法打印详细出错日志,这样乱猜很消耗你的体能和信心。

7年前 评论

建议使用 chunk() 或者cursor() 来读取大量数据库记录,避免内存读满。详细比较可以看这篇 Laravel(Eloquent): chunk() vs cursor() :tada:

7年前 评论
咖啡是個軟件猴

@leo 谢谢大神 今天下午我搞出来了 就是 PHP 内存溢出了。。最后设置到256mb的 memory 才能运行。

7年前 评论
咖啡是個軟件猴

@young 谢谢啦

7年前 评论
咖啡是個軟件猴

@lijinma 不是要分页展示出来, 而是在37万条数据里 搜出来结果大约2w条, 然后每一条里有一个column是 消费金额, 我需要把这两万条的加起来

7年前 评论
咖啡是個軟件猴

@young 还是日语- -。。。。

7年前 评论
leo

@咖啡是個軟件猴 为何不直接用sum

7年前 评论
咖啡是個軟件猴

@leo 您说的直接用是 直接用什么?

7年前 评论
leo

@咖啡是個軟件猴 sql里用sum求和呀

7年前 评论
咖啡是個軟件猴

@leo 对呀 你说的有道理, 新手完全不懂这些 哈哈 刚开始接触3个月

7年前 评论
咖啡是個軟件猴

public function customerHistory(){

    $time = [];

    $sales = [];

    $custno = $_GET['id'];

    $customer = Customer::where('custno',$custno)->first();

    $customerHistory = FullySO::where('custno',$custno)->get();

        for ($i=0; $i <24 ; $i++) {
            $total = 0;
            $month =  date("Y-m", strtotime("-$i month"));

            foreach ($customerHistory as $so) {

                $so_year_month = substr($so->ordate,0,7);
                if($so_year_month==$month){
                    $total  = $total + $so->price;
                }

            }
            array_push($time, $month);

            array_push($sales, $total);

        }

    return view('/history/customerHistory',['customer'=>$customer,'time'=>$time,'sales'=>$sales]);
}

求哪个大神给看看 我这个是不是逻辑上有问题, 所以导致了 很慢, 因为我这个要计算出每个月的销售总额。。

7年前 评论

@young 文中作者提到cursor的方式,一条一条查询,内存按理应该是最小和不变的,但是事实并非如此。对于这点我也有困惑,可惜作者没有解释原因,请问你知道原因吗?

6年前 评论

@CoderPoet 我觉得原文作者的说法有错误,其实 cursor 并不是像文章说的那样一条一条的查询。他和 all() 一样,都是一次查询,得到所有数据 select * from "users"。之所以占内存小是因为,他不是直接输出数组供 foreach 循环,而是使用了 yield 生成器 来输出数据。其实文章说的也对,yield 的语法就是一条一条的输出数据。所以要明白 cursor 的优化原理不像 chunk ,多次查询减少内存,而是一次查询,使用生成器输出数据来减少内存占用。

6年前 评论

@young 感谢!豁然开朗了!难怪使用cursor的时候,内存会先吃掉一大块,然后又持续不断往上涨。不过总体还是比直接all()消耗的内存小。

6年前 评论

另外再想请问下,使用cursor的时候 是第一次就从数据库查到所有数据么,所以内存会吃掉一大块;那么之后得持续不断上涨的内存有什么办法优化?我试过unset变量 ,刷新Buffer,都没效果,而且困惑的是这块内存的消耗是来自于什么?

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!