\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 是基于设置的,但是,它也可能只是获取结果并在内存中处理它们。
还需要记住的是,您每次迭代都运行一条插入语句,这也可能会很费力。