所以我有一个我试图运行的功能,它基本上遍历每个帐户,获得一段时间内的所有销售,将它们相加并将它们存储在数据库中。最终目标是每晚运行此功能,以便在我呈现数据时不必完成(因为在手机上加载页面需要永远)。问题是当我通过加热运行我的计算机并且浏览器超时。有更好的优化方法吗?
现在我通过转到网址(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
答案 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);
虽然有一个潜在的错误,但也预先存在你以前做过的事情。如果一个帐户在过去两年没有任何销售,那么没有什么可以从这个表中删除它们,所以看起来好像他们有去年的销售数据,但他们真的不会。