Как оптимизировать циклы для извлечения больших файлов CSV-файлов - PullRequest
0 голосов
/ 30 октября 2018

У меня вопрос по оптимизации кода. Более десяти лет я не кодировал ничего, кроме простых петель.

Я создал приведенный ниже код, который отлично работает, но очень медленный для моих нужд.

По сути, у меня есть 2 CSV-файла:

  • исходный CSV-файл, содержащий около 500 000 записей, скажем: att1, att2, source_id, att3, att4 (в действительности это около 40 столбцов)
  • основной CSV-файл, содержащий около 120 миллионов записей, скажем: att1, att2, att3, main_id, att4 (в действительности это около 120 столбцов)

Для каждого source_id в исходном файле мой код анализирует основной файл для всех строк, где main_ id == source_id, и записывает каждую из этих строк в новый файл.

Есть ли у вас какие-либо предложения о том, как я могу оптимизировать код, чтобы он работал намного быстрее?

<?php

$mf = "main.csv";
$mf_max_line_length = "512";
$mf_id = "main_id";

$sf = "source.csv";
$sf_max_line_length = "884167";
$sf_id = "source_id";


if (($mf_handle = fopen($mf, "r")) !== FALSE)
{
    // Read the first line of the main CSV file
    // and look for the position of main_id
    $mf_data = fgetcsv($mf_handle, $mf_max_line_length, ",");
    $mf_id_pos = array_search ($mf_id, $mf_data);

    // Create a new main CSV file
    if (($nmf_handle = fopen("new_main.csv", "x")) !== FALSE)
    {
        fputcsv($nmf_handle,$mf_data);
    } else {
        echo "Cannot create file: new_main.csv" . $sf;
        break;
    }
}

// Open the source CSV file
if (($sf_handle = fopen($sf, "r")) !== FALSE)
{
    // Read the first line of the source CSV file
    // and look for the position of source_id
    $sf_data = fgetcsv($sf_handle, $sf_max_line_length, ",");
    $sf_id_pos = array_search ($sf_id, $sf_data);

    // Go trhough the whole source CSV file
    while (($sf_data = fgetcsv($sf_handle, $sf_max_line_length, ",")) !== FALSE)
    {
        // Open the main CSV file
        if (($mf_handle = fopen($mf, "r")) !== FALSE)
        {
            // Go trhough the whole main CSV file
            while (($mf_data = fgetcsv($mf_handle, $mf_max_line_length, ",")) !== FALSE)
            {
                // If the source_id matches the main_id
                // then we write it into the new_main CSV file
                if ($mf_data[$mf_id_pos] == $sf_data[$sf_id_pos])
                {
                    fputcsv($nmf_handle,$mf_data);
                }
            }
            fclose($mf_handle);
        }
    }
    fclose($sf_handle);
    fclose($nmf_handle);
}

?>

1 Ответ

0 голосов
/ 30 октября 2018

Звучит как работа для mysql.

Сначала вам нужно будет создать таблицы на основе всех ваших полей. Смотрите здесь

Затем вы загрузите свои данные. Смотрите здесь

Наконец, вы создадите запрос, подобный:

SELECT * INTO OUTFILE '/tmp/something.csv' 
    FIELDS TERMINATED BY ',' ENCLOSED BY '"' 
    LINES TERMINATED BY '\n' 
FROM source_table INNER JOIN main_table ON 
    source_table.source_id=main_table.main_id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...