laravel进程函数中的大量数据得到了数据库

时间:2016-12-29 21:26:28

标签: php database laravel

所以我有一个我试图运行的功能,它基本上遍历每个帐户,获得一段时间内的所有销售,将它们相加并将它们存储在数据库中。最终目标是每晚运行此功能,以便在我呈现数据时不必完成(因为在手机上加载页面需要永远)。问题是当我通过加热运行我的计算机并且浏览器超时。有更好的优化方法吗?

现在我通过转到网址(localhost:300/account_sales)来运行该功能,因为我对该地址的路由调用了函数(Route::get('/account_sales','UserAccountsController@salesAddToDB');

public function salesAddToDB() {

    $accounts = Account::all();

    foreach ($accounts as $account) 
    {
        $current_month  = 0;
        $current_year   = 0;
        $last_month     = 0;
        $last_year      = 0;

        DB::table('sales')->select('quantity')
        ->where('account_vip_id', $account->vip_id)
        ->whereBetween('date', [
            Carbon::now()->startOfYear()->format('Y-m-d'), 
            Carbon::now()->endOfYear()->format('Y-m-d')
        ])->chunk(50, function($current_year_sales) {
            foreach ($current_year_sales as $sale) {
                $current_year += $sale->quantity;
            }
        });

        DB::table('sales')->select('quantity')
        ->where('account_vip_id', $account->vip_id)
        ->whereBetween('date', [
            Carbon::now()->startOfMonth()->format('Y-m-d'), 
            Carbon::now()->endOfMonth()->format('Y-m-d')
        ])->chunk(50, function($current_month_sales) {
            foreach ($current_month_sales as $sale) {
                $current_month += $sale->quantity;
            }
        });

        DB::table('sales')->select('quantity')
        ->where('account_vip_id', $account->vip_id)
        ->whereBetween('date', [
            Carbon::now()->subYear()->startOfYear()->format('Y-m-d'), 
            Carbon::now()->subYear()->endOfYear()->format('Y-m-d')
        ])->chunk(50, function($last_year_sales) {
            foreach ($last_year_sales as $sale) {
                $last_year += $sale->quantity;
            }
        });

        DB::table('sales')->select('quantity')
        ->where('account_vip_id', $account->vip_id)
        ->whereBetween('date', [
            Carbon::now()->subMonth()->startOfMonth()->format('Y-m-d'), 
            Carbon::now()->subMonth()->endOfMonth()->format('Y-m-d')
        ])->chunk(50, function($last_month_sales) {
            foreach ($last_month_sales as $sale) {
                $last_month += $sale->quantity;
            }
        });

        DB::table('accounts')
        ->where('id', $account->id)
        ->update([
            'current_year'  => $current_year,
            'current_month' => $current_month,
            'last_month'    => $last_month,
            'last_year'     => $last_year
        ]);

        echo $current_year . '<br>';
        echo $current_month . '<br>';
        echo $last_month . '<br>';
        echo $last_year . '<br>';
    }
}

请记住,帐户有40K记录,销售总记录为60K

1 个答案:

答案 0 :(得分:0)

我认为你在这里做了大约100k +的查询。 4为每个帐户选择+ 1插入,我认为这是最大的问题。

这应取代您拥有的所有选择查询。

SELECT
    account_vip_id,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()), quantity, 0)) AS current_year,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE() ), quantity, 0)) AS current_month,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) - 1, quantity, 0)) AS last_year,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE()) - 1, quantity, 0)) AS last_month
FROM sales
GROUP BY account_vip_id

然后,您只需遍历结果并更新/插入您的帐户表。

如果您想进一步,可以进一步修改为插入...选择。您需要在帐户表格中的account_vip_id上添加一个唯一键,然后添加ON DUPLICATE KEY UPDATE,这样可以将您的100k +查询转换为1个查询。

修改

我已经更新了查询以消除循环查询结果的需要,它应该为您处理所有事情而无需在PHP中循环。唯一的条件是您需要帐户上的唯一键,以便我们无法创建重复项。

ALTER TABLE accounts ADD UNIQUE INDEX account (account_vip_id);

查询本身......

INSERT INTO accounts
SELECT
    account_vip_id,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()), quantity, 0)) AS current_year,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE() ), quantity, 0)) AS current_month,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) - 1, quantity, 0)) AS last_year,
    SUM(IF(YEAR(`date`) = YEAR(CURDATE()) AND MONTH(`date`) = MONTH(CURDATE()) - 1, quantity, 0)) AS last_month
FROM sales
GROUP BY account_vip_id
ON DUPLICATE KEY UPDATE
    current_year = VALUES(current_year),
    current_month = VALUES(current_month),
    last_year = VALUES(last_year),
    last_month = VALUES(last_month);

虽然有一个潜在的错误,但也预先存在你以前做过的事情。如果一个帐户在过去两年没有任何销售,那么没有什么可以从这个表中删除它们,所以看起来好像他们有去年的销售数据,但他们真的不会。