Доброго времени суток! На сайте (интернет-магазин) используется система импорта товаров из csv. Алгоритм довольно прост - в прайсе есть, помимо прочего, артикул и бренд. Смысл таков: проверяется артикул - если присутствует в БД, у товара обновляются остатки, цена и т.д. Если отсутствует - проверяем, есть ли вообще такой бренд. Если нет - создаём и кладём туда товар. Если есть - кладём в существующий бренд товар. Система, в принципе, рабочая. Но прайсы по 15 000 наименований, на каждую позицию выходит от 2 до 4 запросов в БД. Итого - получаем нехилую нагрузку на базу при каждом обновлении товаров. Может, кто-то реализовывал подобное, но другими способами? Интересует, как можно оптимизировать скрипт. Буду благодарен за советы, возможно, примеры реализации (более гуманные для мускула).
Может выложите уже существующий код? Попробуйте ставить на крон выполнение.. У крона нет ограничений по времени запроса,нагрузке и т.д
Всё, что приходит в голову сходу - это сделать dump базы, потом локально (или если проблема в железе, то на другом железе) сравнивать дамп и поступления новые, и если показания не сходяться, то обновлять дамп и бд. Или можно делать дамп бд перед каждым обновлением. Мои 2 копейки.
tty0 это, как раз, как не надо делать. Если не очевидно - мы делаем более чем в 2 раза больше действий. Вместо просто заливки 15000 записей - мы вначале загружаем их все, а потом все равно заливаем 15к записей FindeR можно обойтись максимум 2 запросами на каждое наименование. А если бренды сгруппированы - то еще меньше: Code: INSERT IGNORE INTO `brands`(`brand_name`) VALUES ('Название бренда'); REPLACE `articles`(`article_id`, `value`, `items_left`) VALUES ('123456', '100', '1'); 1 запрос - Если бренд существует - запись не будет вставлена. 2 запрос - если запись существует - обновить данные, если записи не существует - вставить её. "Существование" определяется по колонкам с флагами UNIQUE и PRIMARY KEY. Со вторым запросом следует быть внимательным - если существует несколько колонок с индексом UNIQUE - то может быть 'обновлена' более чем одна запись в таблице, перед выполнением следует проверить структуру базы ~30000 запросов - это не так много, тем более что данная операция, скорее всего, не так часто выполняется, и обновление можно производить, когда СУБД не так сильно загружена. Для *никс систем и, если СУБД расположена на той же машине, что и скрипт - лучше использовать локальный Unix-сокет (напр. '/var/mysql/mysql.sock').
-=Zhenek=-, кода много, вряд ли его кто-то будет читать. Крон тут не в тему, админ сам прайсы загружает, всегда разные. Да и отключить таймаут всегда и так можно, не в этом дело. tty0, база там на 30 000 наименований примерно, с прайсов не все обновляются. Gifts, спасибо, интересные мысли. Но сделаю пару уточнений. По поводу INSERT INGNORE - тут поле brand_name не является UNIQUE. Запрос на проверку выглядит так Code: SELECT id FROM brands WHERE brand_name = 'name_from_price' AND enable=1 Т.е. бренд должен быть активен (enable=1), чтобы считаться "существующим". Артикул товара - также не является уникальным. Могут одинаковые встретиться. Я правильно понимаю, что в таком случае REPLACE table некорректно себя поведёт? Или можно условие WHERE или ON дописать? А вот слова "А если бренды сгруппированы - то еще меньше" натолкнули на мысль. Я так понимаю, сначала сравнивать бренды текущей и предыдущей итерации, если совпадают - избавляемся от запросов бренда.
FindeR уникальный индекс может висеть на нескольких столбцах - и уже по этой комбинации будет срабатывать обновление По какому принципу тогда вы вообще обновляете позиции товара? В принципе - да, а если брендов в базе немного - то можно делать выборку всех брендов, заносить их в массив и проверять условие уже внутри ПХП
По артикулу и обновляются. Но т.к. прайсы присылаются различными поставщиками, возможен вариант совпадения артикулов у разных товаров. В таком случае уникальность определяется articul+brand_name. Требование заказчика
FindeR ну и поставьте уникальный индекс на два поля: Code: ALTER TABLE `brands` ADD UNIQUE INDEX `uniq` (`articul`, `brand_name`) ; и если при вставке с помощью REPLACE - эти два поля в какой то строке одновременно совпадут - строка будет обновлена