Laravel - Сохранение множества записей в базе данных

Первый вопрос, укажите, можно ли его прояснить. Я много раз использовал ответы StackOverflow, поэтому спасибо за помощь!

Веб-сайт, который я разрабатываю, должен импортировать множество записей из файла CSV. Преобразование данных и сохранение в данный момент работают, но поскольку в одном файле может быть несколько тысяч записей, импорт данных в БД может быть ОЧЕНЬ долгим.

Как лучше всего сохранить в БД большой массив записей (массив массивов, содержащих данные для каждой записи)?

Вот код, который я использую сейчас:

for ($i = 0; $i < count($participants); $i ++)
    {
        Participant::firstOrCreate( [ 'survey_id' => $participants[$i]['survey_id'],
            'id_importe' => $participants[$i]['id_importe'] ],
            array_merge( $participants[$i], ['token' => $savedInLime[$i]['token']] ) );
    }

Я сохранил построение массива там, но важная часть: есть ли лучший способ, чем цикл в массиве и "firstOrCreating" каждой записи?


РЕДАКТИРОВАТЬ

Я протестировал эти методы с таймером на каждом для файла, содержащего около 3900 записей.

TL; DR: «create» только немного быстрее, чем «firstOrCreate» и «insert» намного медленнее из-за двойного цикла.

1 - Я использовал свой предыдущий код для firstOrCreate, и это заняло 216 секунд

2 - Я использовал этот код для «создания», он был немного быстрее (205 с), но не гарантирует, что запись не является копией.

for ($i = 0; $i < count($participants); $i ++)
    {
        Participant::create( 
            'id_importe' => $participants[$i]['id_importe'] ],
            array_merge( $participants[$i], ['token' => $savedInLime[$i]['token']] ) );
    }

3 - Я использовал этот код для вставки (возможно, это можно было бы сделать быстрее с помощью функции массива), и это заняло 460 секунд. Мне пришлось использовать array_chunk из-за предела заполнителя базы данных (я думаю, немного выше 60k).

    $tmp = array();
    for ($i = 0; $i < count($participants); $i ++){
        $tmp[] = array_merge( $participants[$i], ['token' => $savedInLime[$i]['token']] );
    }
    $inserts = array_chunk($tmp, 2000);
    foreach ($inserts as $insert){
        Participant::insert($insert);
    }

И вы не уверены, есть ли конкретная запись в БД или нет, поэтому вам нужно проверить ее перед тем, как вводить. Это так?

Adre Astrian 09.07.2018 12:38

Попробуйте синхронизировать Laravel или прикрепить / отсоединить: //laravel.com/docs/5.6/eloquent-relationships#upda‌ ting-many-to-many-re‌ lationships

Vipul 09.07.2018 12:38

Да, @AdreAstrian, пользователи будут импортировать файлы, поэтому они могут ошибаться. Записи не существуют, поэтому, если я не ошибаюсь, это не создание отношения.

LeprechaunCode 09.07.2018 13:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
106
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуй это:

$participants = [
    ['participant_id' => 11, 'survey_id' => 1),
    ['participant_id' => 22, 'survey_id' => 2),
];

Participant::insert($participants);

Но это не коснется меток времени IIRC.

Это, безусловно, быстрее, но не будет проверять, есть ли уже предмет. Возможно, я решу, что это лучше, проведя тест по первому элементу, чтобы увидеть, существует ли он. Это вопрос времени, чтобы получить VS анти-двойная безопасность ... Обновлено: для этой таблицы не нужны временные метки.

LeprechaunCode 09.07.2018 14:02

Я протестировал несколько методов, но, похоже, вставка не работает быстрее, если вы не думаете, что мой метод "вставки" можно значительно улучшить?

LeprechaunCode 09.07.2018 16:50
Ответ принят как подходящий

Просто для тех, кто достаточно новичок, чтобы не знать лучше:

В итоге я сохранил технику loop + firstOrCreate, поскольку потеря времени по сравнению с выигрышем в надежности была незначительной.

Другие вопросы по теме