@billybons2006

Как лучше сравнить базу данных и текстовый файл (артикул-цена, больше 2000 строк)?

Я очень сори за простецкий вопрос, но сформулировать точнее не смог: как правильнее (чтобы не перегружать хостинг) сравнить цены из текстового файла (2000-3000 строк) и из базы данных, основываясь на артикуле?

Ну, считал я из файла артикулы и цены в массив.

$data[0][acticle]
$data[0][price]

А дальше как сравнить базу данных и полученный массив?

Не запускать же для каждого артикула из файла новый SELECT типа:

foreach ($data as $key) {
	// само собой, ниже просто идея, а не запрос
	SELECT * FROM table WHERE article LIKE %$key['article']%
	...
	
	//Ну и дальше что надо - цену обновить, например или не обновлять, в зависимости от условий...
	
	if цена_из_бд > $key['price']
		UPDATE table SET price=$key['price'] WHERE article=$key['article']
}


Или только так и иначе никак? Это ж 2000-3000 запросов надо сделать. Бред, вроде бы.

Я немного боюсь, не напряжно ли это для хостинга да и вообще, может, это в корне неверная идея?

Вроде сейчас 2000 строк это ерунда, но ведь их (строк) может стать 10000 через год...
  • Вопрос задан
  • 419 просмотров
Пригласить эксперта
Ответы на вопрос 4
@FanatPHP
Чебуратор тега PHP
Несколько вещей чисто для информации, чтобы ты немного начал ориентироваться в окружающем пространстве. Потому что, как все новички, ты думаешь совершенно не о том.
1. 2000 строк - это не база, а песочница с куличиками. И 10 - тоже. О нагрузках можно начинать думать начиная с сотен тысяч.
2. САМЫЙ ад в твоих рассуждениях - это LIKE, который ты считаешь штатным средством поиска по артикулу. Вот с такими идеями даже и меленькую базу можно поставить колом.
3. Стандартный вариант работы в таких случаях - читаешь файл в массив, чтобы артикулы были ключами. Дальше запрашиваешь все строки из БД, и читая по одной, ищешь артикул в массиве.
4. Непонятно, зачем в текущей формулировке вообще доставать и сравнивать. Почему нельзя просто в цикле проапдейтить 2000 строк, указывая условия в запросе?
5. Почему у тебя в вопросе ничего нет про удаленные/добавленные строки? Если за этим следить не надо, то задача и вовсе выеденного яйца не стоит. Или ты об том пока не думал?
Ответ написан
EnterSandman
@EnterSandman
Эникей
ну, вы же не ежеминутно будете это делать?
не напряжно это и вполне нормально
Ответ написан
Tantacula
@Tantacula
Ларавельщик, витающий в небесах.
php.ru/manual/ref.array.html

PHP, конечно, много памяти жрет для массивов, но не столько, чтобы вытаскивать по одной строке из базы с целью экономии памяти. Возьмите все строки из базы за один запрос, преобразуйте в нужный массив, обработайте его, затем обновите базу вторым запросом. Когда количество элементов в массиве превысит сто тысяч, почитайте эту статью habrahabr.ru/post/141093 и погуглите, есть довольно интересные советы про оптимизацию по этому поводу... хотя после всех них единственным разумным вариантом кажется скрипт на питоне. Но это уже когда в массивах будет под миллион элементов.
Ответ написан
kashey
@kashey
Программирую большую половину жизни
Даже если такой запрос будет выполнять 5 минут - это совершенно нормально для операции которая выполняется раз в день.
Улучшить ситуацию можно через хранимки или начать использовать https://php.net/manual/ru/mysqli.multi-query.php
С другой стороны у вас совершенно "упушен" момент про индексы, и условия в первом и втором запросе различаются.
Что можно сделать чтобы было "совсем хорошо"
1. Установить тип поля артикуля в char[точный размер]. Вообще "fixed" таблицы, где размер строки всегда можно заранее посчитать работают лучше.
2. Добавить UNIQUE индекс на артикуль. Он же уникальный?
3. Идем по "новым записям" и "INSERT INTO table(...)... ON DUPLICATE KEY UPDATE price=newprice. В общем инсертим строки, но если такая есть - обновляем.
3.1 Если новых строк нет вообще - делаем только апдейты
3.2 Если есть - заводим еще одно поле - "dirty". В начале ставим в 0, в инсертах и апдейтах ставим в 1. После окончания работы строк, которые не обновлялись" будет 0.
4. Можно еще вспомнить, что любые строковые индексы работают плохо, как бы вы их не спрашивали. Можно добавить еще одно поле crc=CRC32(article), которая переведет строку в число.
4.1 Итого UNIQUE вешается на два поля - crc(первое), article
4.2 В WHERE выражениях можно делать WHERE crc=CRC32(?) and article=? - это будет работать очень сильно быстрее и без коллизий.

А вообще можно особо и не париться, например обновлять данные "в лоб" на локальном компе, а потом переливать дампы.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы