Итак, в основном я пытаюсь импортировать данные примерно в 15 разных таблиц в свою базу данных из другой. Я фрагментирую данные из исходной базы данных и в рамках этого обратного вызова функции вставляю их в свою базу данных, используя необработанный SQL. Пример кода:
foreach($tables as $table) {
DB::connection('source_db')->table($table)->select($fields)->orderBy('id'))->chunk(2500, function($records) use($table) {
$this->runInsertQuery($records, $table);
});
}
Всего около 2 миллионов записей, кажется, что он начинается очень быстро, но становится все медленнее и медленнее по мере того, как он перемещается от таблицы к таблице, что занимает несколько часов. На основе документации Laravel у меня сложилось впечатление, что разбиение на фрагменты заставит вставки работать намного быстрее, но, похоже, имеет противоположный эффект. Будем признательны за любые рекомендации!
«разбивка на фрагменты заставит вставки работать намного быстрее», чем при отсутствии фрагментов, а не просто «быстрее и быстрее с течением времени».
Но мой вопрос в том, что заставляет его двигаться все медленнее и медленнее с течением времени, и что я могу сделать, чтобы предотвратить это?
Вы отслеживали использование памяти приложениями? Я мог себе представить, что со временем скрипт использует почти всю доступную память, что требует от сборщика мусора правильного выполнения своей работы. С меньшими скриптами вы часто даже не видите работающего сборщика мусора, потому что скрипт завершается до того, как у вас закончится память. Так что, может быть, попробуйте использовать больше памяти и следить за своей памятью. Вы также можете попробовать добавить gc_collect_cycles() (принудительная сборка мусора) в конце или после того, как каждый фрагмент что-то меняет.
Вы должны изолировать снижение производительности. Это часть чтения и разбивки на части? Или это часть процесса вставки? Вы можете попробовать заменить $this->runInsertQuery($records, $table) функцией, которая ничего не делает, и посмотреть, будет ли у вас по-прежнему замедление. Если вы это сделаете, попробуйте увеличить ваши куски. Причина возможного замедления? Чтение фрагмента занимает время, пропорциональное тому, сколько фрагментов уже было прочитано. ... LIMIT 2500 OFFSET 25000000 может быть довольно медленным.
@ O.Jones, вы правы, чтение фрагментов занимает все больше времени для каждого фрагмента, что, кажется, является источником замедления. Спасибо за вашу помощь!
Можете ли вы показать определение таблицы, которую вы читаете? (SHOW CREATE TABLE tablename)? Пожалуйста редактировать свой вопрос.






Для этого воспользуйтесь инструментом
mysqldump.