Сравнение нескольких очень больших CSV-файлов друг с другом - PullRequest
0 голосов
/ 02 октября 2011

У меня есть n csv-файлов, которые мне нужно сравнить друг с другом и впоследствии изменить.Проблема в том, что каждый CSV-файл содержит около 800 000 строк.

Для чтения CSV-файла я использую fgetcsv , и он работает хорошо.Получить немного памяти, но в конце концов это достаточно быстро.Но если я пытаюсь сравнить массив друг с другом, это займет годы.

Еще одна проблема заключается в том, что мне нужно использовать foreach для получения данных csv с помощью fgetcsv из-за количества файлов n.Я получаю один ультра большой массив и не могу сравнить его с array_diff.Поэтому мне нужно сравнить его с вложенными циклами foreach, которые занимают целую вечность.

фрагмент кода для лучшего понимания:

foreach( $files as $value ) {
    $data[] = $csv->read( $value['path'] );
}

мой класс csv использует fgetcsv для добавления вывода в массив:

fgetcsv( $this->_fh, $this->_lengthToRead, $this->_delimiter, $this->_enclosure )

Все данные всех CSV-файлов хранятся в массиве $ data.Вероятно, это первая большая ошибка, связанная с использованием только одного массива, но я понятия не имею, как сохранять гибкость при работе с файлами без использования foreach.Я пытался использовать гибкие имена переменных, но я тоже там застрял:)

Теперь у меня есть этот большой массив.Обычно, если я пытаюсь сравнить значения друг с другом и выяснить, существуют ли данные из первого файла во втором файле и т. Д., Я использую array_diff или array_intersect.Но в этом случае у меня есть только один большой массив.И, как я сказал, для запуска foreach требуется несколько веков.

Кроме того, после всего 3 файлов у меня есть массив с 3 * 800.000 записей.Я думаю, что после 10 файлов моя память взорвется.

Так есть ли лучший способ использовать PHP для сравнения n очень больших файлов CSV?

1 Ответ

4 голосов
/ 02 октября 2011

Использовать SQL

  • Создать таблицу с теми же столбцами, что и ваши файлы CSV.
  • Вставить данные из первого файла CSV.
  • Добавление индексов для ускорения запросов.
  • Сравните с другими файлами CSV, прочитав строку и выполнив SELECT.

Вы не описали, как вы сравниваете n файлов, иЕсть несколько способов сделать это.Если вы просто хотите найти строку, которая находится в A1, но не в A2, ..., An, тогда вам просто нужно добавить логический столбец diff в вашу таблицу.Если вы хотите узнать, в каких файлах строка повторяется, вам понадобится текстовый столбец или новая таблица, если строка может быть в нескольких файлах.

Редактировать: несколькоНесколько слов о производительности, если вы используете MySQL (сейчас я не особо разбираюсь в других СУБД).

Вставка строк одна за другой будет слишком медленной.Вы, вероятно, не сможете использовать LOAD DATA, если не можете поместить файлы CSV непосредственно в файловую систему сервера БД.Поэтому я думаю, что лучшее решение - это прочитать несколько сотен строк в CSV, а затем отправить запрос множественной вставки INSERT INTO mytable VALUES (..1..), (..2..).

Вы не можете выдать SELECT для каждой строки, которую вы читаете в другойфайлы, так что вам лучше положить их в другую таблицу.Затем выполните обновление для нескольких таблиц, чтобы отметить строки, идентичные в таблицах t1 и t2: UPDATE t1 JOIN t2 ON (t1.a = t2.a AND t1.b = t2.b) SET t1.diff=1

Возможно, вы можете попробовать использовать sqlite.Здесь нет проблем с параллелизмом, и это может быть быстрее, чем модель клиент / сервер MySQL.И вам не нужно много настраивать для использования sqlite.

...