У меня есть файл csv, который может варьироваться от 50 000 до более 100 тыс. Строк данных.Импорт больших CSV-файлов в MySQL с использованием Laravel
Я в настоящее время использую Laravel w/Laravel Forge, MySQL и Maatwebsite Laravel Excel.
Это будет использоваться конечным пользователем, а не сам, так что я создал простую форму на мой взгляд лезвия как таковой:
{!! Form::open(
array(
'route' => 'import.store',
'class' => 'form',
'id' => 'upload',
'novalidate' => 'novalidate',
'files' => true)) !!}
<div class="form-group">
<h3>CSV Product Import</h3>
{!! Form::file('upload_file', null, array('class' => 'file')) !!}
</div>
<div class="form-group">
{!! Form::submit('Upload Products', array('class' => 'btn btn-success')) !!}
</div>
{!! Form::close() !!}
Это затем сохраняет файл на сервере успешно и я m теперь можно выполнить итерацию результатов, используя что-то вроде цикла foreach.
Теперь вот вопросы, я сталкиваюсь в хронологическом порядке и исправления/попытках: (10k строки тесты CSV файл)
- [вопрос] PHP таймаут.
- [средство] Изменено для асинхронного запуска с помощью команды задания.
- [результат] Импортирует до 1500 строк.
- [issue] У сервера заканчивается память.
- [средство правовой защиты] Добавлен swap-накопитель в 1gb.
- [результат] Импортирует до 3000 строк.
- [issue] У сервера заканчивается память.
- [средство правовой защиты] Включены результаты chunking из 250 строк каждого фрагмента.
- [результат] Импортирует до 5000 строк.
- [issue] У сервера заканчивается память.
- [средство правовой защиты] Удалена какая-либо трансаполяция/объединение таблиц.
- [результат] Импортирует до 7000 строк.
Как вы можете видеть, результаты незначительны и нигде вблизи 50k, я едва могу сделать это около 10k.
Я прочитал и посмотрел на возможные предложения, такие как:
- Используйте необработанный запрос для запуска Загрузки данных Local входной_файла.
- Разделить файлы перед импортом.
- Храните на сервере, затем сервер разбивается на файлы и обрабатывает их cron.
- Обновите мою капюшон размером 512 МБ до 1 ГБ в качестве последнего средства.
Идет загрузка данных с локальной загрузкой данных может не работать, потому что мои столбцы заголовков могут меняться на один файл, поэтому у меня есть логика для обработки/итерации через них.
Разделение файлов перед импортом в порядке до 10 000, но для 50 тыс. Или более? Это было бы крайне непрактично.
Хранить на сервере, а затем сервер разбивать его и запускать отдельно, не беспокоя конечного пользователя? Возможно, но даже не уверен, как это сделать на PHP, но только кратко прочитал об этом.
Также обратите внимание, что мой работник очереди установлен на таймаут за 10000 секунд, что также очень непрактично и плохо работает, но, похоже, это единственный способ, которым он будет продолжать работать до того, как память ударит.
Теперь я могу сдавать и просто обновлять память до 1 гб, но я чувствую, что в лучшем случае он может подпрыгнуть меня до 20 тыс. Строк до того, как он снова не сработает. Что-то нужно обрабатывать все эти строки быстро и эффективно.
Наконец здесь проблеск моей таблицы структуры:
Inventory
+----+------------+-------------+-------+---------+
| id | profile_id | category_id | sku | title |
+----+------------+-------------+-------+---------+
| 1 | 50 | 51234 | mysku | mytitle |
+----+------------+-------------+-------+---------+
Profile
+----+---------------+
| id | name |
+----+---------------+
| 50 | myprofilename |
+----+---------------+
Category
+----+------------+--------+
| id | categoryId | name |
+----+------------+--------+
| 1 | 51234 | brakes |
+----+------------+--------+
Specifics
+----+---------------------+------------+-------+
| id | specificsCategoryId | categoryId | name |
+----+---------------------+------------+-------+
| 1 | 20 | 57357 | make |
| 2 | 20 | 57357 | model |
| 3 | 20 | 57357 | year |
+----+---------------------+------------+-------+
SpecificsValues
+----+-------------+-------+--------+
| id | inventoryId | name | value |
+----+-------------+-------+--------+
| 1 | 1 | make | honda |
| 2 | 1 | model | accord |
| 3 | 1 | year | 1998 |
+----+-------------+-------+--------+
Full CSV Sample
+----+------------+-------------+-------+---------+-------+--------+------+
| id | profile_id | category_id | sku | title | make | model | year |
+----+------------+-------------+-------+---------+-------+--------+------+
| 1 | 50 | 51234 | mysku | mytitle | honda | accord | 1998 |
+----+------------+-------------+-------+---------+-------+--------+------+
Так быстро прогоне моей логики процесса как можно проще было бы:
- Загрузить файл в Maatwebsite/Laravel -Excel и итерации через цепочку с петлями
- Проверьте, не потеряны ли категории_id и sku, иначе игнорируют и регистрируют ошибку в массиве.
- Lookup category_id и вытащите все соответствующие поля столбца из всех связанных таблиц, которые он использует, а затем, если в базу данных не было нулевой вставки.
- Создайте собственное название, используя больше логики, используя поля, доступные в файле.
- Промыть и повторить.
- Наконец, экспортируйте массив ошибок в файл и запишите его в базу данных для загрузки, чтобы просмотреть ошибки в конце.
Я надеюсь, что кто-то может поделиться со мной некоторыми соображениями относительно некоторых возможных идей о том, как я должен заниматься этим, имея в виду использование Laravel, а также то, что это не простая загрузка, мне нужно обрабатывать и размещать в разных связанных таблицах в строке else я бы сразу загрузил данные.
Спасибо!
Все ли файлы csv вставлены в одну и ту же таблицу? Если это так, я не понимаю, почему использование 'load data local infile' будет проблемой - некоторые столбцы будут просто' NULL'. Вы можете использовать Python (выполняемый через дочерний процесс PHP через 'exec()') для анализа файла по мере необходимости после загрузки на сервер, но перед его вставкой в таблицу. – Terry
@Terry Это всего лишь один CSV-файл, но он вставлен в несколько таблиц, как указано выше, почему я не смог легко использовать локальную информацию о нагрузке. Кроме того, данные изменяются для каждого файла в зависимости от того, какая категория будет задействована, которая будет иметь разные столбцы. Также из-за этой переменной теперь будет сложно указать тип данных для каждого поля. – dmotors
Если это просто файл CSV, то использование пакета Maatwebsite Laravel Excel и PHPExcel слишком велико, хотя пакет Maatwebsite Laravel Excel делает (я считаю) доступ к функциям chunking PHPExcel для загрузки файла –