Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Алгоритмы > Алгоритм для импорта большого прайса |
Автор: Hinikato 28.4.2011, 23:09 | ||
Здравствуйте! Суть задачи такая: есть около 10 000 (10 тысяч) продуктов в прайсе в формате XML. Нужно импортировать все продукты в базу данных. У каждого продукта есть собственный код по которому можно искать в базе. Задача сводится к тому, что по коду продукта нужно смотреть в базе, есть там уже продукт с таким кодом и если есть, просто обновлять информацию, если нет, то добавлять. Но есть ограничение: нельзя делать много запросов в базу для выборки, т.е. 10000 запросов SELECT неприемлимо. Выбирать все в массив, тоже не выход, т.к. в базе может быть около 1000 000 продуктов. Если выбрать все 1000000 записей получим для худшего случая такой расход памяти:
UTF-8 может занимать 2 байта, поэтому 2, умножаем на макс. кол-во символов в коде и умножаем на общее кол-во продуктов в базе, после чего получаем кол-во мегабайт. Поэтому нужен какой-то алгоритм, который позволит искать продукты по коду с меньшим количеством запросов. Пример кода продукта: "abcd" - это просто строка длиной до 255 символов. Можете ли вы посоветовать такой алгоритм или просто подсказать/показать как тут можно поступить? |
Автор: Akina 28.4.2011, 23:52 |
Грузим файл на сайт, средствами SQL импортируем его в таблицу и одним запросом получаем необходимые данные. |
Автор: Lipetsk 29.4.2011, 08:03 | ||
откуда 10000 запросов? |
Автор: Hinikato 29.4.2011, 12:41 | ||
Akina, можно подробнее, насколько я понял, вы описали кратко саму суть задачи, а не ее решение. Добавлено через 2 минуты и 21 секунду В цикле мы идем по продуктам, для каждого продукта мы ищем в базе его код, если продукт с таким кодом найден в базе, мы делаем UPDATE, иначе, делаем INSERT. Прояснило ли это для вас суть задачи? |
Автор: ksnk 29.4.2011, 15:31 | ||
Вряд ли получится одним запросом для 100000 строк ![]() А так - все просто. Строим такую-же временную таблицу, как и таблица товаров, строим запросы "insert ... values" с максимальными количествами товаров и исполняем. После заполнения временной таблицы - запрос на изменения - один и запрос на вставку - другой. Разумнее, все-таки, на компьютер клиента, на котором строится XML таблица, поставить скрипт преобразования всего этого добра в SQL, и грузить на сервер именно sql запрос. |
Автор: Hinikato 29.4.2011, 15:47 | ||||||
Похоже немного непонятен мой вопрос. Вот краткий псевдокод, чтобы стала понятна суть:
Каждый вызов FindProductByCodeInDB() это один SELECT:
Если у нас 10000 продуктов, то получаем 10000 селектов. Как преобразовать это дело можно, чтобы не выбирать все коды в память, а потом в памяти искать. Объясню почему не получится выбрать все 1000 000 кодов из базы одним запросом. Потому что это получится:
а такой расход памяти недопустим. Поэтому вопрос, как можно это оптимизировать? Я надеюсь может вы подскажете какой алгоритм есть особый который позволяет как-то умно уменьшить кол-во селектов и искать продукт по коду в базе/памяти. |
Автор: ksnk 29.4.2011, 16:21 |
--Не нужно искать товары отдельными запросами. --Нужно импортировать маловразумительную xml таблицу в базу данных, в отдельную таблицу, специально для этого дела создаваемую. --Для этого импорта лучше всего подходят длинные и быстрые "insert...values..." запросы. Именно ими оперируют все процедуры импорта-экспорта менеждеров баз данных. --Кто и где будет делать sql дамп не суть важно, хотя я предпочел бы, чтобы клиент, так как сервер и так занят. Для этого нужно поставить несложный конвертер (можно на php ;) ) на клиентскую машину. Для такого очень удобны фреймворки, которые умеют делать консольные приложения. После успешного импорта таблицы товаров в новую таблицу на сервере, операция импорта товаров становится достаточно тривиальной. |
Автор: Hinikato 30.4.2011, 05:56 |
ksnk, наконец-то, надеюсь, я понял вашу идею, спасибо, умное решение ![]() У меня остались некоторые вопросы по той части, о которой вы говорите как о тривиальной. В результате мы получим две похожих таблицы: - в первой таблице будут храниться товары для импорта, загруженные из XML, - во вторую нам нужно будет их перенести. Это как я понял можно сделать SQL запросом, но тут вопрос каким. Ведь он должен решать по-сути ту же саму задачу: обновить те товары, код которых совпадает и вставка тех товаров, код которых не совпадает. Мои вопросы такие: 1. Можно привести хотя бы набросок SQL запроса, чтобы я понял общий смысл? 2. Можно ли это сделать без хранимой процедуры, при этом не забыв, что делать 1000 000 запросов неприемлимо? Или все-таки здесь не обойтись без хранимой процедуры? |
Автор: almagnit 30.4.2011, 10:25 | ||
Если productCode является уникальным или первичным ключом то можно пользоваться такими запросами
В случае совпадения какого-нибудь ключа, СУБД самостоятельно обработает исключение и выполнит UPDATE для указанных столбцов. |
Автор: Hinikato 30.4.2011, 11:27 | ||||||||
almagnit, изящно, спасибо, взял себе как способ одним запросом обновить строку или вставить ее. Я кажется понял, как можно это сделать: выбираем коды всех продуктов у которых product_code совпал:
В худшем случае их кол-во будет равно кол-ву импортируемых товаров, таким образом массив не будет превышать 10000 кодов продуктов, а это равно:
Размер такого массива допустимо выбирать в память и искать продукты по коду в нем. Спасибо ребята за помощь ;) Тема закрыта, если кто-то еще не хочет ее чем-то дополнить. |