Пакетная вставка данных в базу данных MySQL с использованием php - PullRequest
3 голосов
/ 25 июня 2009

У меня есть тысячи данных, проанализированных из огромного XML, для вставки в таблицу базы данных с использованием PHP и MySQL. Моя проблема в том, что все данные заносятся в таблицу слишком долго. Есть ли способ, которым мои данные делятся на более мелкие группы, чтобы процесс вставки был по группе? Как настроить скрипт, который будет обрабатывать данные, например, на 100? Вот мой код:

foreach($itemList as $key => $item){
     $download_records  = new DownloadRecords();
    //check first if the content exists
    if(!$download_records->selectRecordsFromCondition("WHERE Guid=".$guid."")){
         /* do an insert here */
    } else {
         /*do an update */
    }

}

* примечание: $ itemList составляет около 62 000 и продолжает расти.

Ответы [ 3 ]

3 голосов
/ 25 июня 2009

Использование цикла for?

Но самый быстрый вариант загрузки данных в MySQL - это использовать команду LOAD DATA INFILE , вы можете создать файл для загрузки через PHP, а затем передать его в MySQL через другой процесс (или как последний шаг в первоначальном процессе).

Если вы не можете использовать файл, используйте следующий синтаксис:

insert into table(col1, col2) VALUES (val1,val2), (val3,val4), (val5, val6)

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

РЕДАКТИРОВАТЬ: Учитывая ваш фрагмент, кажется, вы можете воспользоваться синтаксисом INSERT ... ON DUPLICATE KEY UPDATE *1013*, позволяющим базе данных выполнять свою работу и уменьшающему количество запросов. Предполагается, что ваша таблица имеет первичный ключ или уникальный индекс.

Чтобы попасть в БД каждые 100 строк, вы можете сделать что-то вроде ( ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ ЕГО И ИСПРАВИТЕ В СВОЮ СРЕДУ )

$insertOrUpdateStatement1 = "INSERT INTO table (col1, col2) VALUES ";
$insertOrUpdateStatement2 = "ON DUPLICATE KEY UPDATE ";
$counter = 0;
$queries = array();

foreach($itemList as $key => $item){
    $val1 = escape($item->col1); //escape is a function that will make 
                                 //the input safe from SQL injection. 
                                 //Depends on how are you accessing the DB

    $val2 = escape($item->col2);

    $queries[] = $insertOrUpdateStatement1. 
    "('$val1','$val2')".$insertOrUpdateStatement2.
    "col1 = '$val1', col2 = '$val2'";

    $counter++;

    if ($counter % 100 == 0) {
        executeQueries($queries);
        $queries = array();
        $counter = 0;
    }
}

И executeQueries будет захватывать массив и отправлять один множественный запрос:

function executeQueries($queries) {
   $data = "";
     foreach ($queries as $query) {
        $data.=$query.";\n";
    }
    executeQuery($data);
}
0 голосов
/ 25 июня 2009

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

Для загрузки используйте только Интернет.

Если вы действительно хотите импортировать в БД по веб-запросу, вы можете выполнить массовую вставку или использовать как минимум транзакцию, которая должна быть быстрее.

Затем для ограничения вставок партиями по 100 (совершение транзакции, если счетчик равен% 100 == 0), и повторяйте, пока не будут вставлены все ваши строки.

0 голосов
/ 25 июня 2009

Да, просто делай то, что ожидал.

Не следует пытаться выполнить массовую вставку из веб-приложения, если вы считаете, что можете достичь тайм-аута и т. Д. Вместо этого отбросьте файл куда-нибудь и у вас будет демон, хрон и т. Д., Выберите его и запустите пакетное задание (Если выполняется cron, убедитесь, что одновременно запускается только один экземпляр).

...