Реалізація масового імпорту товарів (Bulk Import) на сайт

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація масового імпорту товарів (Bulk Import) на сайт
Середня
~5 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація масового імпорту товарів

Масовий імпорт — це одноразова завантаження тисяч або сотень тисяч позицій. На відміну від інкрементального оновлення, завдання інше: за розумний час обробити весь обсяг, не положивши базу даних та не зайнявши всі воркери черги на добу.

Розмір має значення: стратегії за обсягом

Обсяг Метод Час обробки
До 1 000 позицій Синхронно в запиті Секунди
1 000–50 000 Одна очередна задача з чанками Хвилини
50 000–500 000 Fan-out: N паралельних Jobs 10–60 хвилин
Понад 500 000 Batch insert + окремий конвеєр Години

Принцип chunk + queue

Файл з 100 000 рядків не обробляється в один Job. Файл розбивається на чанки, кожен чанк — окремий Job:

class BulkImportDispatcher
{
    private const CHUNK_SIZE = 500;

    public function dispatch(ImportFile $file): void
    {
        $import = ImportRun::create([
            'file_id'    => $file->id,
            'status'     => 'dispatching',
            'total'      => 0,
        ]);

        $chunkIndex = 0;
        foreach ($file->parser()->chunks(self::CHUNK_SIZE) as $chunk) {
            ProcessImportChunkJob::dispatch($import->id, $chunkIndex, $chunk)
                ->onQueue('bulk-import');
            $chunkIndex++;
        }

        $import->update([
            'status'       => 'processing',
            'total_chunks' => $chunkIndex,
        ]);
    }
}

Bulk Upsert замість поштучних операцій

Головний інструмент продуктивності — INSERT ... ON CONFLICT DO UPDATE (upsert). Laravel підтримує через Model::upsert():

class ProcessImportChunkJob implements ShouldQueue
{
    public int $timeout = 120;

    public function handle(): void
    {
        $rows = [];
        foreach ($this->chunk as $item) {
            $rows[] = [
                'sku'         => $item['sku'],
                'name'        => $item['name'],
                'price'       => $item['price'],
                'updated_at'  => now(),
            ];
        }

        // Один SQL-запит замість 500 окремих
        Product::upsert(
            $rows,
            uniqueBy: ['sku'],
            update: ['name', 'price', 'updated_at']
        );

        DB::table('import_runs')
            ->where('id', $this->importId)
            ->increment('processed_chunks');
    }
}

Одна операція upsert для 500 рядків у PostgreSQL займає ~50–200 мс — проти 500 × 5 мс = 2500 мс для поштучних запитів.

Передзавантаження справочників у пам'ять

Найдорожча операція при імпорті — запити до БД для розв'язання залежностей (категорія за назвою, постачальник за ID, тег за slug). Рішення — завантажити всі справочники в пам'ять перед обробкою:

class ImportContext
{
    private array $categoryMap;   // ['name' => id]
    private array $supplierMap;   // ['code' => id]
    private array $existingSkus;  // ['sku' => product_id]

    public function preload(int $sourceId): void
    {
        $this->categoryMap  = Category::pluck('id', 'name')->all();
        $this->supplierMap  = Supplier::pluck('id', 'code')->all();
        $this->existingSkus = Product::where('source_id', $sourceId)
            ->pluck('id', 'sku')->all();
    }

    public function resolveCategoryId(string $name): ?int
    {
        return $this->categoryMap[$name] ?? null;
    }
}

Для 200 000 SKU цей словник займає ~10–20 МБ пам'яті — допустимо для воркера.

Обмеження навантаження

Під час масового імпорту важливо не деградувати сайт:

  • Виділити окрему чергу bulk-import з обмеженим числом воркерів (2–4)
  • Основну чергу default не трогати
  • Запускати тяжелий імпорт в ночі через Laravel Scheduler
  • Використовувати транзакції по чанку, не по всьому файлу

Тривалість реалізації

  • Chunk-диспетчер, bulk upsert, передзавантаження справочників — 2 дні
  • Bus::batch з фінальним коллбеком, post-import конвеєр — +1 день
  • Прогрес в admin UI, обмеження навантаження, ночний планувальник — +1 день