如何限制从 eloquent 查询中检索到的信息并阻止它崩溃?
How to limit the information retrieved from an eloquent query and stop it crashing?
以下代码遍历整个公司数据库和缓存的较低级别嵌套关系,以便日后可以访问它们。当数据超过约 20,000 家公司和约 500,000 个嵌套关系时,这会消耗大量内存并死亡。我如何修改它(将其更改为原始 SQL 或 Laravel 查询构建器语句),以便它仅加载我需要的信息并提高性能? (足以统计条目状态)。
嵌套关系如下
- 公司>(有很多)地点>(有很多)设备>(有
许多)项目>(有一个)订单
- 公司>(有很多)协议>(有很多)设备
- 公司 >(有很多)潜在客户
- 公司>(有很多)发票
脚本应该输出每个公司的以下事物的数量
- maintainedCount - 活动设备的数量(即具有状态
'Active') 的有效协议(即状态为
'Unsigned'、'Active' 或 'Cancel on Expiry')
- equipmentCount - 活动设备的数量(即
'Active')
状态
- leadCount - 活动线索的数量(即状态为
'Open')
- invoiceCount - 有效发票的数量(即状态为
'Pending' 或 'Complete')
- projectCount - 活动项目的数量(即状态为
'Pending' 或 'Complete')
- orderCount - 活动订单的数量(即状态为
'Pending' 或 'Complete')
当前脚本如下;
Company::chunk(50, function($companies) {
foreach ($companies as $company) {
$maintainedCount = 0;
$equipmentCount = 0;
$leadCount = 0;
$invoiceCount = 0;
$projectCount = 0;
$orderCount = 0;
foreach ($company->agreements as $agreement) {
if (in_array($agreement->status, ['Unsigned', 'Active', 'Cancel on Expiry'])) {
$maintainedCount += $agreement->equipment->where('status', 'Active')->count();
}
}
$equipmentCount = $company->equipment->where('status', 'Active')->count();
$unmaintainedCount = ($equipmentCount - $maintainedCount);
$leadCount= $company->leads->where('status', 'Open')->count();
foreach ($company->invoices as $invoice) {
if (in_array($invoice->status, ['Pending', 'Complete'])) {
$invoiceCount += 1;
}
}
foreach ($company->equipment as $equipment) {
foreach ($equipment->projects as $project) {
if (in_array($project->status, ['Pending', 'Complete'])) {
$projectCount += 1;
}
if($project->order <> null) {
if (in_array($project->order->status, ['Pending', 'Complete'])) {
$orderCount += 1;
}
}
}
}
DB::table('companies')->where('id', $company->id)->update(['unmaintained_count' => $unmaintainedCount, 'lead_count' => $leadCount, 'project_count' => $projectCount, 'order_count' => $orderCount, 'invoice_count' => $invoiceCount]);
}
});
$this->info('Company count cache updated!');
好的,我已经通过将其转换为直接 SQL 查询(4gb+ 到 100mb)解决了内存使用问题
DB::connection()->disableQueryLog();
$start = microtime(true);
Company::chunk(50, function($companies) {
foreach ($companies as $company) {
$maintainedCount = 0;
$equipmentCount = 0;
$leadCount = 0;
$invoiceCount = 0;
$projectCount = 0;
$orderCount = 0;
$maintainedCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT equipment.id FROM equipment
INNER JOIN agreements ON agreements.id = equipment.agreement_id
WHERE agreements.company_id = :companyId
AND equipment.status = "Active"
AND (agreements.status = "Active" OR agreements.status = "Unsigned" OR agreements.status = "Cancel on Expiry")) AS QUERY;'),
['companyId' => $company->id])[0]);
$equipmentCount = $company->equipment->where('status', 'Active')->count();
$unmaintainedCount = ($equipmentCount - $maintainedCount);
$leadCount= $company->leads->where('status', 'Open')->count();
$invoiceCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT invoices.id
FROM invoices
WHERE invoices.company_id = :companyId
AND (invoices.status = "Pending" OR invoices.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
$projectCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT projects.id FROM projects
INNER JOIN equipment ON equipment.id = projects.equipment_id
INNER JOIN locations ON locations.id = equipment.location_id
WHERE locations.company_id = :companyId
AND (projects.status = "Pending" OR projects.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
$orderCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT orders.id FROM orders
INNER JOIN projects ON projects.id = orders.project_id
INNER JOIN equipment ON equipment.id = projects.equipment_id
INNER JOIN locations ON locations.id = equipment.location_id
WHERE locations.company_id = :companyId
AND (orders.status = "Pending" OR orders.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
DB::table('companies')->where('id', $company->id)->update(['unmaintained_count' => $unmaintainedCount, 'lead_count' => $leadCount, 'project_count' => $projectCount, 'order_count' => $orderCount, 'invoice_count' => $invoiceCount]);
}
});
$duration = number_format((microtime(true) - $start), 2);
$this->info('Company count cache updated! (it took '.$duration.' seconds)');
以下代码遍历整个公司数据库和缓存的较低级别嵌套关系,以便日后可以访问它们。当数据超过约 20,000 家公司和约 500,000 个嵌套关系时,这会消耗大量内存并死亡。我如何修改它(将其更改为原始 SQL 或 Laravel 查询构建器语句),以便它仅加载我需要的信息并提高性能? (足以统计条目状态)。
嵌套关系如下
- 公司>(有很多)地点>(有很多)设备>(有 许多)项目>(有一个)订单
- 公司>(有很多)协议>(有很多)设备
- 公司 >(有很多)潜在客户
- 公司>(有很多)发票
脚本应该输出每个公司的以下事物的数量
- maintainedCount - 活动设备的数量(即具有状态 'Active') 的有效协议(即状态为 'Unsigned'、'Active' 或 'Cancel on Expiry')
- equipmentCount - 活动设备的数量(即 'Active') 状态
- leadCount - 活动线索的数量(即状态为 'Open')
- invoiceCount - 有效发票的数量(即状态为 'Pending' 或 'Complete')
- projectCount - 活动项目的数量(即状态为 'Pending' 或 'Complete')
- orderCount - 活动订单的数量(即状态为 'Pending' 或 'Complete')
当前脚本如下;
Company::chunk(50, function($companies) {
foreach ($companies as $company) {
$maintainedCount = 0;
$equipmentCount = 0;
$leadCount = 0;
$invoiceCount = 0;
$projectCount = 0;
$orderCount = 0;
foreach ($company->agreements as $agreement) {
if (in_array($agreement->status, ['Unsigned', 'Active', 'Cancel on Expiry'])) {
$maintainedCount += $agreement->equipment->where('status', 'Active')->count();
}
}
$equipmentCount = $company->equipment->where('status', 'Active')->count();
$unmaintainedCount = ($equipmentCount - $maintainedCount);
$leadCount= $company->leads->where('status', 'Open')->count();
foreach ($company->invoices as $invoice) {
if (in_array($invoice->status, ['Pending', 'Complete'])) {
$invoiceCount += 1;
}
}
foreach ($company->equipment as $equipment) {
foreach ($equipment->projects as $project) {
if (in_array($project->status, ['Pending', 'Complete'])) {
$projectCount += 1;
}
if($project->order <> null) {
if (in_array($project->order->status, ['Pending', 'Complete'])) {
$orderCount += 1;
}
}
}
}
DB::table('companies')->where('id', $company->id)->update(['unmaintained_count' => $unmaintainedCount, 'lead_count' => $leadCount, 'project_count' => $projectCount, 'order_count' => $orderCount, 'invoice_count' => $invoiceCount]);
}
});
$this->info('Company count cache updated!');
好的,我已经通过将其转换为直接 SQL 查询(4gb+ 到 100mb)解决了内存使用问题
DB::connection()->disableQueryLog();
$start = microtime(true);
Company::chunk(50, function($companies) {
foreach ($companies as $company) {
$maintainedCount = 0;
$equipmentCount = 0;
$leadCount = 0;
$invoiceCount = 0;
$projectCount = 0;
$orderCount = 0;
$maintainedCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT equipment.id FROM equipment
INNER JOIN agreements ON agreements.id = equipment.agreement_id
WHERE agreements.company_id = :companyId
AND equipment.status = "Active"
AND (agreements.status = "Active" OR agreements.status = "Unsigned" OR agreements.status = "Cancel on Expiry")) AS QUERY;'),
['companyId' => $company->id])[0]);
$equipmentCount = $company->equipment->where('status', 'Active')->count();
$unmaintainedCount = ($equipmentCount - $maintainedCount);
$leadCount= $company->leads->where('status', 'Open')->count();
$invoiceCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT invoices.id
FROM invoices
WHERE invoices.company_id = :companyId
AND (invoices.status = "Pending" OR invoices.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
$projectCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT projects.id FROM projects
INNER JOIN equipment ON equipment.id = projects.equipment_id
INNER JOIN locations ON locations.id = equipment.location_id
WHERE locations.company_id = :companyId
AND (projects.status = "Pending" OR projects.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
$orderCount = reset(DB::select(DB::raw('SELECT COUNT(*) FROM (
SELECT orders.id FROM orders
INNER JOIN projects ON projects.id = orders.project_id
INNER JOIN equipment ON equipment.id = projects.equipment_id
INNER JOIN locations ON locations.id = equipment.location_id
WHERE locations.company_id = :companyId
AND (orders.status = "Pending" OR orders.status = "Complete")) AS QUERY;'),
['companyId' => $company->id])[0]);
DB::table('companies')->where('id', $company->id)->update(['unmaintained_count' => $unmaintainedCount, 'lead_count' => $leadCount, 'project_count' => $projectCount, 'order_count' => $orderCount, 'invoice_count' => $invoiceCount]);
}
});
$duration = number_format((microtime(true) - $start), 2);
$this->info('Company count cache updated! (it took '.$duration.' seconds)');