\Rpn\Services\Onv\Models\OnvForm\EmissionsStationarySource::select("onvos_request_emissions_stationary_sources.*") ->join('onvs', function ($join) { $join->on('onvs.service_request_id', '=', 'onvos_request_emissions_stationary_sources.service_request_id'); }) ->whereNotNull('geometry') ->chunk(1000, function ($stationaries) { \DB::transaction(function () use ($stationaries) { $layer = \Rpn\Services\Map\Models\MapLayer::MAP_LAYER_STATIONARY; $type = \Rpn\Services\Onv\Models\OnvForm\EmissionsStationarySource::class; /** @var \Rpn\Services\Onv\Models\OnvForm\EmissionsStationarySource $stationary */ foreach ($stationaries as $stationary) { $id = $stationary->id; if (empty($stationary->geometry)) { continue; } $geo = json_encode($stationary->geometry); try { $point = \GeoJson\GeoJson::jsonUnserialize($stationary->geometry); } catch (\Throwable $e) { continue; } \DB::statement(" insert into map_objects(map_layer_id, model_type, model_id, geometry, created_at, updated_at) values(${layer}, '${type}', ${id}, ST_MakeValid(ST_GeomFromGeoJSON('${geo}')), now(), now()) on conflict do nothing; "); } }); });
接下來的程式碼給了我一個記憶體限制錯誤(允許的記憶體大小 2147483648 位元組已耗盡)。儘管我使用的是遊標和塊,為什麼它會以這種方式工作?我該如何修復它?
P粉3409802432024-03-29 00:34:20
如果您想了解有關如何修復內存限制的更多信息,在此答案中對此進行了半回答。根據它運行的作業系統,您只需相應地調整位置即可。
如果您詢問內部發生了什麼,可能有多種情況。是的,您正在對資料進行分塊,但如果不進行偵錯,則很難僅從程式碼中判斷出來(我個人會修補問題)。
可能是像你這樣的事情
if (empty($stationary->geometry)) { continue; }
當您之前已經檢查了 geometry
不為 null 的位置。老實說,它可以將其轉化為任何東西。 SQL 中的循環很慢,因為 SQL 是基於設定的,但是,它也可能只是取得結果並在記憶體中處理它們。
還需要記住的是,您每次迭代都會執行一條插入語句,這也可能會很費力。