首页  >  问答  >  正文

如何解决 Laravel 迁移中的内存限制问题?

\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粉373596828P粉373596828228 天前397

全部回复(1)我来回复

  • P粉340980243

    P粉3409802432024-03-29 00:34:20

    如果您想了解有关如何修复内存限制的更多信息,在此答案中对此进行了半回答。根据它运行的操作系统,您只需相应地调整位置即可。

    如果您询问内部发生了什么,可能有多种情况。是的,您正在对数据进行分块,但如果不进行调试,则很难仅从代码中判断出来(我个人会修补问题)。

    可能是像你这样的事情

    if (empty($stationary->geometry)) {
      continue;
    }

    当您之前已经检查了 geometry 不为 null 的位置时。老实说,它可以将其转化为任何东西。 SQL 中的循环很慢,因为 SQL 是基于设置的,但是,它也可能只是获取结果并在内存中处理它们。

    还需要记住的是,您每次迭代都运行一条插入语句,这也可能会很费力。

    回复
    0
  • 取消回复