首頁  >  問答  >  主體

如何解決 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粉373596828179 天前351

全部回覆(1)我來回復

  • P粉340980243

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

    如果您想了解有關如何修復內存限制的更多信息,在此答案中對此進行了半回答。根據它運行的作業系統,您只需相應地調整位置即可。

    如果您詢問內部發生了什麼,可能有多種情況。是的,您正在對資料進行分塊,但如果不進行偵錯,則很難僅從程式碼中判斷出來(我個人會修補問題)。

    可能是像你這樣的事情

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

    當您之前已經檢查了 geometry 不為 null 的位置。老實說,它可以將其轉化為任何東西。 SQL 中的循環很慢,因為 SQL 是基於設定的,但是,它也可能只是取得結果並在記憶體中處理它們。

    還需要記住的是,您每次迭代都會執行一條插入語句,這也可能會很費力。

    回覆
    0
  • 取消回覆