Лучшие практики для итерации по КРУПНЫМ файлам CSV в PHP

Я не вижу никакого вреда, пока данные меньше - но лучше отфильтровать данные на уровне БД, чтобы избежать возможных ошибок нехватки памяти.

7
задан alex 11 May 2009 в 01:17
поделиться

6 ответов

Выполните ОБЪЕМНЫЙ ИМПОРТ в базу данных (SQL Server, который я использую). ОБЪЕМНЫЙ ИМПОРТ занимает буквально секунды, а 100 000 записей - это мелочь для базы данных, чтобы справиться с бизнес-правилами. Я регулярно выполняю аналогичный анализ данных для таблицы с более чем 4 миллионами строк, и это не займет 10 минут, которые вы указали.

РЕДАКТИРОВАТЬ: Я должен указать, да, я не рекомендую PHP для этого. Вы'

12
ответ дан 6 December 2019 в 15:29
поделиться

The simple key to this is keeping as much work out of the inner loop as possible.

Simply put, anything you do in the inner loop is done "100K times", so doing nothing is best (but certainly not practical), so doing as little possible is the next best bet.

If you have the memory, for example, and it's practical for the application, defer any "output" until after the main processing. Cache any input data if practical as well. This works best for summary data or occasional data.

Ideally, save for the reading of the CSV file, do as little I/O as possible during the main processing.

Does PHP offer any access to the Unix mmap facility, that is typically the fastest way to read files, particularly large files.

Another consideration is to batch your inserts. For example, it's straightforward to build up your INSERT statements as simple strings, and ship them to the server in blocks of 10, 50, or 100 rows. Most databases have some hard limit on the size of the SQL statement (like 64K, or something), so you'll need to keep that in mind. This will dramatically reduce your round trips to the DB.

If you're creating primary keys through simple increments, do that en masses (blocks of 1000, 10000, whatever). This is another thing you can remove from your inner loop.

And, for sure, you should be processing all of the rules at once for each row, and not run the records through for each rule.

1
ответ дан 6 December 2019 в 15:29
поделиться

Вы можете попробовать запустить импорт CSV из командной строки PHP. Обычно это дает более быстрые результаты.

0
ответ дан 6 December 2019 в 15:29
поделиться

Если вы используете PHP для выполнения этой работы, переключите синтаксический анализ на Python, поскольку он НАМНОГО быстрее, чем PHP в этом отношении, этот обмен должен ускорить процесс на 75% или даже больше.

Если вы используете MySQL, вы также можете использовать оператор LOAD DATA INFILE, хотя я не уверен, нужно ли вам проверять данные, прежде чем вставлять их в базу данных.

0
ответ дан 6 December 2019 в 15:29
поделиться

100 тыс. Записей - небольшое количество. 10 минут - неплохое время для обработки одного потока. Объем необработанной работы, которую необходимо выполнить по прямой линии, вероятно, составляет около 10 минут, независимо от того, используете ли вы PHP или C. Если вы хотите, чтобы это было быстрее, вам понадобится более сложное решение, чем цикл while. ,

Вот как я бы решил это:

  1. Используйте решение map / reduce, чтобы запустить процесс параллельно. Hadoop, вероятно, избыточен. Свинья-латынь может сделать эту работу. Вы действительно просто хотите, чтобы карта была частью проблемы карты / уменьшения. IE: вы создаете часть файла для обработки подпроцессом. Ваш редуктор, вероятно, cat . Простая версия могла бы иметь процессы форка PHP для каждого блока записи размером 10 КБ, ждать потомков, затем повторно соберите их вывод.
  2. Используйте модель обработки очереди / сетки. Выложите в очередь фрагменты файла, а затем создайте кластер машин, проверяющих, захватывающих задания и отправляющих данные куда-то. Это очень похоже на модель map / reduce, только с использованием других технологий, плюс вы можете масштабировать, добавляя больше машин в сетку.
  3. Если вы можете написать свою логику как SQL, сделайте это в базе данных. Я бы избегал этого, потому что большинство веб-программистов не могут работать с SQL на этом уровне. Кроме того, SQL ограничен для выполнения таких операций, как проверки RBL или поиск ARIN.
1
ответ дан 6 December 2019 в 15:29
поделиться

Некоторое время мы интенсивно работали над этой проблемой. И, да, лучшее решение - читать только часть файла за один раз, анализировать ее, выполнять проверку, выполнять фильтрацию, затем экспортировать ее, а затем читать следующую часть файла. Я согласен, что это, вероятно, не решение для php, хотя вы, вероятно, можете сделать это на php. Пока у вас есть функция поиска, чтобы вы могли начать чтение из определенного места в файле. Вы правы, это добавляет более высокий уровень сложности, но стоит этих небольших дополнительных усилий. Если ваши данные чистые, т. Е. Правильно разделены, квалифицированы по строкам, не содержат разорванных строк и т. Д., Тогда обязательно массовая загрузка в базу данных sql. В противном случае вы хотите знать, где, когда и почему возникают ошибки, и уметь их обрабатывать.

0
ответ дан 6 December 2019 в 15:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: