Как выполнить SQL-подобное объединение в Perl?

Я должен обработать некоторые данные путем объединения двух разных файлов. У обоих из них есть два столбца, которые образуют первичный ключ, который я могу использовать, чтобы сопоставлять их рядом. Файлы в вопросах огромные (около 5 ГБ с 20 миллионами строк), поэтому мне нужен эффективный код. Как бы я сделал это в Perl?

Я приведу пример:

Если файл A содержит столбцы

id, name, lastname, dob, school

Файл B содержит столбцы

address, id, postcode, dob, email

Мне нужно объединить эти два файла, сопоставив id и dob в двух файлах, чтобы получить выходной файл со столбцами:

 id, name, lastname, dob, school, address, postcode, email

6 ответов

Думаю, я бы просто создал новую базу данных mysql/sqlite/what и вставил строки. Должно быть ~20 строк perl.

Это, конечно, требует легкого доступа к БД.

Думаю, вы также можете отсортировать файлы по интересующим полям, а затем для каждой строки в file1 найти и распечатать соответствующие строки в file2.

Старый способ сделать это - использовать системные утилиты для сортировки обоих файлов в последовательности ключей, а затем сопоставлять их построчно. Прочитайте оба файла, если ключи совпадают, выведите данные. Если они не совпадают, читайте файл с меньшим ключом, пока они не совпадут. Установите бесконечно высокий ключ для файла, если он нажмет eof. Когда оба ключа бесконечно высоки, все готово.

Также вы можете попробовать DBD::AnyData

Я на самом деле не пробовал это, но более креативное решение может быть:

  1. Прочитайте каждый файл один раз и создайте карту между уникальными комбинациями id+dob и их позициями в файле. Используйте скажи ().
  2. Создать карту в Perl
  3. Чтение фактических данных из файлов с использованием позиций на карте и sysread()
  4. Запишите данные в новый файл

Или просмотрите эту прекрасную статью Techrepublic. Тем не менее, вам все еще может потребоваться 5 ГБ памяти. Интересно, где бы вы могли использовать утилиты сортировки / объединения CLI unix/linux? Просто мысль.

Вы также можете использовать мой 3-летний модуль CPAN Set::Relation, который предназначен для таких вещей, что позволяет вам выполнять все функции SQL, такие как join в Perl. Создайте объект Set::Relation для каждого файла, а затем используйте метод join(). Тем не менее, этот реализованный модуль будет хранить все ваши операнды и приводить к памяти, поэтому он ограничен вашей оперативной памятью. Но вы все равно можете посмотреть в его источнике, как работает join(), а затем реализовать на его основе более эффективную версию для ваших целей.

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