幕布斯6054654
也许这个查询返回了这么多元素,PHP大部分时间都花在了将对象包裹在它们周围。如果要查看在查询本身上花费了多少时间,可以直接在 控制台 () 上运行它,或者在代码中使用CollectionPostgreSQL Serverphp artisan tinkerDB::listenpublic function exportAll(Request $request){ // PHP >= 7.4.0 DB::listen(fn($query) => dump($query->sql, $query->bindings, $query->time)); // PHP < 7.4.0 DB::listen(function ($query) { dump($query->sql, $query->bindings, $query->time); }); ...}如果包装是问题所在,请尝试使用 .它自 .您可以通过调用而不是 来使用它。CollectionLazyCollectionLaravel 6.0$data->cursor()$data->get()A基本上是一个对象,您可以迭代并使用一些方法。它们允许您处理数据,而无需为X行量构建大量行的开销。LazyCollectionCollectionCollection有关惰性集合的更多信息我将重新发布您的函数,并进行一些我认为会对性能产生积极影响的更改。exportAllpublic function exportAll(Request $request){ $data = AssetRepository::query(); //From AssetRepository Function $headers = array( 'Content-Type' => 'text/csv', 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', 'Content-Disposition' => 'attachment; filename=export.csv', 'Expires' => '0', 'Pragma' => 'public', ); $response = new StreamedResponse(function () use ($data) { $handle = fopen('php://output', 'w'); /** * Use a LazyCollection instead * $getData = $data->get(); */ $getData = $data->cursor(); $remark = Remark::all(['id','label','type']); $remarkAsset = RemarkAsset::all(['asset_id','value','remark_id']); /** * Since we are using a LazyCollection, * we can't treat $getData as an array directly. * * $getHeader = array_keys((array)$getData[0]); */ $getHeader = array_keys((array)$getData->get(0)); $newArray = array(); /** * This can be achieved with array_combine * * $setHeader = array(); * * foreach ($getHeader as $header) { * $setHeader[$header] = $header; * } */ $setHeader = array_combine($getHeader, $getHeader); /** * $remarkHeader is unnecesary. You can just call $remark->toArray() instead. * Also, what you're trying to do with the following foreach can be done with * a combination of array_merge and array_combine * * $remarkHeader = []; //result * * foreach ($remark as $headerRemark) { * $remarkHeader[] = array( * 'id' => $headerRemark['id'], * 'label' => $headerRemark['label'], * 'type' => $headerRemark['type'] * ); * * $setHeader[$headerRemark['type']] = $headerRemark['type']; * } */ $setHeader = array_merge( $setHeader, array_combine( $remark->pluck('type')->toArray(), $remark->pluck('type')->toArray() ) ); /** * Again, $remarkAssets is unnecessary. All you're doing with this loop * is the same as calling $remarkAsset->toArray() * * $remarkAssets = []; * foreach ($remarkAsset as $assetRemark) { * $remarkAssets[] = (array)array( * 'asset_id' => $assetRemark['asset_id'], * 'value' => $assetRemark['value'], * 'remark_id' => $assetRemark['remark_id'] * ); * } */ array_push($newArray, (object)$setHeader); // $coountData = count($getData) / 4; /** * $getData is already a Collection. Here, you're telling PHP to rebuild it * for no reason. For large collections, this adds a lot of overhead. * You can already call the chunk method on $getData anyways. * You could do $chunk = $getData->chunk(500) for example. * It's not even necessary to make a new variable for it since you won't use * $chunk again after this. * * $chunk = collect($getData); * $chunk->chunk(500); * * Also, according to the docs you're not using chunk properly. * https://laravel.com/docs/6.x/collections#method-chunk * You're supposed to loop twice because the chunk method doesn't alter the collection. * If you run * $chunk->chunk(500) * foreach($chunk as $data) { ... } * You're still looping over the entire Collection. * Since your code is not made to work with chunks, I'll leave it like that * * foreach ($chunk as $data) { */ foreach ($getData as $data) { /** * This seems to return an array of the keys of $remarkAssets * where 'asset_id' is equal to $data->id. * You can achieve this through Collection methods on $remarkAsset instead. * * $theKey = array_keys( * array_combine( * array_keys($remarkAssets), * array_column($remarkAssets, 'asset_id') * ), * $data->id * ); * * Since there is no real need to return an array, I'll leave $theKey as a collection. */ $theKey = $remarkAsset->where('asset_id', $data->id)->keys(); /** * Since $remarkHeader doesn't exist in this context, we use $remark instead * * foreach ($remarkHeader as $head) { * * Since $theKey is a collection, the count is obtained * through the count() Collection method. Also, since you don't * ever use $countKey again, you could inline it instead. * * $countKey = count($theKey); * * if ($countKey > 0) { */ foreach ($remark as $head) { if ($theKey->count() > 0) { $valueRemark = ''; foreach ($theKey as $key) { /** * Since $remark is a collection and $head an object * the following if statement needs to be rewritten * * if ($remarkAssets[$key]['remark_id'] == $head['id']) { * $valueRemark = $remarkAssets[$key]['value']; * } */ if ($remark->get($key)->remark_id == $head->id) { $valueRemark = $remark->get($key)->value; } } /** * $data being a stdClass, you can just set the property instead of * going through the trouble of casting it as an array, setting a value * and then re-casting it as an object. * * $data = (array)$data; * $data[$head['type']] = $valueRemark; * $data = (object)$data; * } else { * $data = (array)$data; * $data[$head['type']] = ''; * $data = (object)$data; */ $data->{$head['type']} = $valueRemark; } else { $data->{$head['type']} = ''; } } array_push($newArray, $data); } $chunkArray = collect($newArray); /** * As explained earlier, your use of chunk() doesn't do anything. * We can then safely remove this line. * * $chunkArray->chunk(500); */ foreach ($chunkArray as $datas) { if (is_object($datas)) $datas = (array)$datas; fputcsv($handle, $datas); } fclose($handle); }, 200, $headers); return $response->send();}没有所有评论public function exportAll(Request $request){ $data = AssetRepository::query(); //From AssetRepository Function $headers = array( 'Content-Type' => 'text/csv', 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', 'Content-Disposition' => 'attachment; filename=export.csv', 'Expires' => '0', 'Pragma' => 'public', ); $response = new StreamedResponse(function () use ($data) { $handle = fopen('php://output', 'w'); $getData = $data->cursor(); $remark = Remark::all(['id','label','type']); $remarkAsset = RemarkAsset::all(['asset_id','value','remark_id']); $getHeader = array_keys((array)$getData->get(0)); $newArray = array(); $setHeader = array_combine($getHeader, $getHeader); $setHeader = array_merge( $setHeader, array_combine( $remark->pluck('type')->toArray(), $remark->pluck('type')->toArray() ) ); array_push($newArray, (object)$setHeader); foreach ($getData as $data) { $theKey = $remarkAsset->where('asset_id', $data->id)->keys(); foreach ($remark as $head) { if ($theKey->count() > 0) { $valueRemark = ''; foreach ($theKey as $key) { if ($remark->get($key)->remark_id == $head->id) { $valueRemark = $remark->get($key)->value; } } $data->{$head['type']} = $valueRemark; } else { $data->{$head['type']} = ''; } } array_push($newArray, $data); } $chunkArray = collect($newArray); foreach ($chunkArray as $datas) { if (is_object($datas)) $datas = (array)$datas; fputcsv($handle, $datas); } fclose($handle); }, 200, $headers); return $response->send();}您还可以使用懒惰的集合来备注和备注资产模型,就像这样$remark = Remark::select('id','label','type')->cursor();$remarkAsset = RemarkAsset::select('asset_id','value','remark_id')->cursor();