Как ускорить процесс выполнения запроса в БД?

Привет всем! В таблице есть почти 500к записей. Всего три столбца: id, url, data.
В столбце data хранится json. Каждый день выполняется запрос, который создает массив из тоже примерно 500к записей и потом циклом я проверяю есть ли в бд запись с таким url и если есть, то присваивает полю data единицу, если такого урл нет в базе, то создает новую запись.
Это всё работает ну очень долго, в районе 2х часов.
Прикрепляю код:
foreach ($data as $key => $item) {
	$res = $mysqli->query("SELECT * FROM `name` WHERE url = '".$item['url']."'");
	if($res->num_rows){
		$mysqli->query("UPDATE `name` SET data = '1' WHERE url = '".$item['url']."'");
	} else{
		$mysqli->query("INSERT INTO `name` (url, data) VALUES ('".$item['url']."','".$item['price']."')");
	}
}
  • Вопрос задан
  • 445 просмотров
Решения вопроса 1
@Quieteroks
php программист
Какой тип таблиц используете?
Если InnoDB, то при частых обновления и вставках, в больших таблицах, вы всегда будете получать подобный результат. Самый простой способ в этом случае ускорить, перенести таблицу в MyISAM.

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

И третье. Обновляйте по id, зачем же вы ищете, потом опять ищете для обновления по url. Строчку вы уже получили, можно так считать. Используйте сразу id. И вообще запрос упростите, пишите SELECT `id` FROM... Другие данные Вам не нужны. И ускорите получение и ускорите обновление.

Кстати. Четвертое. Если вы все равно всем записям меняете поле data на 1, можно так же обновление сделать пачкой. Собирайте id найденных записей и обновляйте через UPDATE `name` SET `data` = '1' WHERE `id` IN (1,2,5,7,88,123).
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
@RidgeA
Какая длинна значений url?
Можно сделать уникальный индекс по полю url и потом одним запросом обновить все
https://dev.mysql.com/doc/refman/5.7/en/insert-on-...
Только про json я не понял
Ответ написан
Therapyx
@Therapyx
Data Science
ко всему, что написали сверху - сделайте индексацию нужных полей. Вы про это ничего не написали, а индексация как правило очень и очень серьезно повышает производительность бинарного поиска, вставки и удалений.
Ответ написан
Комментировать
@serikamanco Автор вопроса
Спасибо всем. Создал индексы, добавил поле offer_id, которое гораздо короче, чем урл и буду пробовать!
Ответ написан
Комментировать
2ball
@2ball
Хардкор кодер
Дополнительно перейдите на PDO, используйте PREPARED_STATEMENTS, отключите буферизацию и эмуляцию подготовленных запросов в PDO. PHP очень сильно выжирает ресурсы по эмуляции. А с подготовленными запросами MySQL не будет каждый раз парсить сам запрос. Достаточно биндить значения и отправлять.
Ответ написан
Комментировать
Fragster
@Fragster
помогло? отметь решением!
Не может 500к записей в таких запросах работать больше 2 часов. при 500 к записей даже при тэйбл скан это будет в диапазоне минут (размер строки не более пол килобайта, соответственно, 250 мегабайт на таблицу, что примерно 10-30 секунд на 5400 хдд на запрос селект и апдейт). Ну, или машина совсем старая или виртуалка, ужатая по ресурсам.
В данном случае посоветую сделать таблицу с индексом по хэшу урл (для ограничения длины колонки с индексом) и проверять его. В зависимости от бизнес логики может быть можно сократить запрос до insert .. on duplicate key update
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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