У меня есть тысячи данных, обработанных из огромного 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 */ }
}
* note: $ itemList составляет около 62 000 и продолжает расти.
Использование цикла for?
Но самый быстрый способ загрузки данных в MySQL – использовать команду LOAD DATA INFILE , вы можете создать файл для загрузки через PHP, а затем передать его в MySQL через другой процесс (или как последний шаг в исходном процессе).
Если вы не можете использовать файл, используйте следующий синтаксис:
insert into table(col1, col2) VALUES (val1,val2), (val3,val4), (val5, val6)
поэтому вы сокращаете общее количество предложений для запуска.
EDIT: Учитывая ваш фрагмент, кажется, вы можете воспользоваться синтаксисом MySQL INSERT … ON DUPLICATE KEY UPDATE , позволяя базе данных выполнять работу и уменьшая количество запросов. Это предполагает, что ваша таблица имеет первичный ключ или уникальный индекс.
Чтобы попасть в БД каждые 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); }
Да, просто делайте то, что вы ожидаете делать.
Вы не должны пытаться делать массовую вставку из веб-приложения, если считаете, что можете нанести вред таймауту и т. Д. Вместо этого напишите файл где-нибудь и получите демона или cron и т. Д., Заберите его и запустите пакетное задание (если выполняется с помощью cron, что только один экземпляр запускается сразу).
Вы должны поместить его, как было сказано ранее, в каталог temp с заданием cron для обработки файлов, чтобы избежать тайм-аутов (или потери пользователя сети).
Используйте только веб-страницы для загрузки.
Если вы действительно хотите импортировать в БД по веб-запросу, вы можете либо сделать массовую вставку, либо использовать хотя бы транзакцию, которая должна быть быстрее.
Затем для ограничения вставок партиями 100 (совершение вашего trasnsaction, если счетчик считается% 100 == 0) и повторять до тех пор, пока все ваши строки не будут вставлены.