Этот код должен циклично выполнить более чем 3,5 миллиона строк, как я могу сделать его более эффективным?

У меня есть файл CSV, который имеет 3,5 миллиона кодов в нем.
Я должен указать, что это только КОГДА-ЛИБО будет этим однажды.

csv похож

age9tlg,  
rigfh34,  
...

Вот мой код:

ini_set('max_execution_time', 600);
ini_set("memory_limit", "512M");
$file_handle = fopen("Weekly.csv", "r");
while (!feof($file_handle)) {
    $line_of_text = fgetcsv($file_handle);

    if (is_array($line_of_text))
        foreach ($line_of_text as $col) {
            if (!empty($col)) {
                mysql_query("insert into `action_6_weekly` Values('$col', '')") or die(mysql_error());
            }
    } else {
        if (!empty($line_of_text)) {
            mysql_query("insert into `action_6_weekly` Values('$line_of_text', '')") or die(mysql_error());
        }
    }
}
fclose($file_handle);

Этот код собирается умереть часть путь через на мне? Будет моя память и макс. время выполнения быть достаточно высокой?

NB: Этот код будет выполнен на моем localhost и базе данных, находится на том же ПК, таким образом, задержка не является проблемой.


Обновление:

вот другая возможная реализация. Этот делает это, оптом вставляет 2 000 записей

$file_handle = fopen("Weekly.csv", "r");
$i = 0;
$vals = array();
while (!feof($file_handle)) {
    $line_of_text = fgetcsv($file_handle);

    if (is_array($line_of_text))
        foreach ($line_of_text as $col) {
            if (!empty($col)) {
                if ($i < 2000) {
                    $vals[] = "('$col', '')";
                    $i++;
                } else {
                    $vals = implode(', ', $vals);
                    mysql_query("insert into `action_6_weekly` Values $vals") or die(mysql_error());
                    $vals = array();
                    $i = 0;
                }
            }
        } else {
        if (!empty($line_of_text)) {
            if ($i < 2000) {
                $vals[] = "('$line_of_text', '')";
                $i++;
            } else {
                $vals = implode(', ', $vals);
                mysql_query("insert into `action_6_weekly` Values $vals") or die(mysql_error());
                $vals = array();
                $i = 0;
            }
        }
    }
}
fclose($file_handle);

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


Обновление 2

таким образом я нашел, что могу использовать

LOAD DATA LOCAL INFILE  'C:\\xampp\\htdocs\\weekly.csv' INTO TABLE  `action_6_weekly` FIELDS TERMINATED BY  ';' ENCLOSED BY  '"' ESCAPED BY  '\\' LINES TERMINATED BY  ','(`code`)

но проблема теперь - то, что, я был неправ относительно формата CSV, это - на самом деле 4 кода и затем разрыв строки, таким образом, fhroflg, qporlfg, vcalpfx, rplfigc,
vapworf, flofigx, apqoeei, clxosrc,
...

таким образом, я должен смочь указать две СТРОКИ, ЗАВЕРШЕННЫЕ
этот вопрос был расширен к Здесь.


Обновление 3

При установке его, чтобы сделать объем вставляет 20k строк, с помощью

while (!feof($file_handle)) {
   $val[] = fgetcsv($file_handle);
   $i++;
   if($i == 20000) {
      //do insert
      //set $i = 0;
      //$val = array();
   }
}

//do insert(for last few rows that dont reach 20k

но это умирает в этой точке, потому что по некоторым причинам $val содержит 75k строки и идею почему?
обратите внимание, что вышеупомянутый код упрощен.

6
задан Community 23 May 2017 в 11:54
поделиться

6 ответов

Я сомневаюсь, что это будет популярный ответ, но я бы попросил ваше приложение php запускать mysqlimport в файле csv. Конечно, он оптимизирован намного больше, чем вы делаете в php.

21
ответ дан 8 December 2019 в 04:28
поделиться

этот код умрет частично через меня? будет моя память и макс время выполнения достаточно велико?

Почему бы вам не попытаться выяснить?

Вы можете настроить ограничения как для памяти ( memory_limit ), так и для времени выполнения ( max_execution_time ) , так что, если вам действительно нужно это использовать, это не должно быть проблемой.

Обратите внимание, что MySQL поддерживает отложенную вставку и вставку нескольких строк:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

http://dev.mysql.com/doc/refman/5.1/en/insert.html

3
ответ дан 8 December 2019 в 04:28
поделиться

Вы должны накапливать значения и вставлять их в базу данных сразу в конце или партиями каждые x записей. Выполнение одного запроса для каждой строки означает 3,5 миллиона SQL-запросов, каждый из которых несет определенные накладные расходы.

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

Настоящий ответ - это ответ evilclown: импорт в MySQL из CSV - уже решенная проблема.

0
ответ дан 8 December 2019 в 04:28
поделиться
  1. убедитесь, что в вашей таблице нет индексов , поскольку индексы будут замедлять вставку (добавляйте индексы после того, как вы выполнили все вставки)
  2. , а не создать новый оператор SQL при каждом вызове цикла try и Подготовить оператор SQL вне цикла и выполнить этот подготовленный оператор с параметрами внутри цикла. В зависимости от базы данных это может быть намного быстрее.

Я сделал это при импорте большой базы данных Access в Postgres с помощью perl и уменьшил время вставки до 30 секунд. Я бы использовал инструмент импорта, но я хотел, чтобы Perl обеспечивал соблюдение некоторых правил при вставке.

1
ответ дан 8 December 2019 в 04:28
поделиться

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

0
ответ дан 8 December 2019 в 04:28
поделиться

2 возможных способа.

1) Пакетный процесс, затем запланированное задание импортирует файл, одновременно обновляя статус. Таким образом, вы можете иметь страницу, которая постоянно проверяет статус и обновляется, если статус еще не достиг 100%. Пользователи будут иметь актуальную информацию о том, сколько всего было сделано. Но для этого вам нужен доступ к ОС, чтобы установить задачу по расписанию. И задача будет простаивать, когда нечего импортировать.

2) Пусть страница обработает 1000 строк (или любое N-ное количество строк... решайте сами), затем пошлет java-скрипт браузеру, чтобы он обновился с новым параметром, чтобы сообщить скрипту, что нужно обработать следующие 1000 строк. Вы также можете отобразить статус для пользователя, пока это происходит. Единственная проблема заключается в том, что если страница каким-то образом не обновится, то импорт остановится.

0
ответ дан 8 December 2019 в 04:28
поделиться
Другие вопросы по тегам:

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