Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Алгоритм для импорта большого прайса 
V
    Опции темы
Hinikato
Дата 28.4.2011, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.2.2007

Репутация: нет
Всего: нет



Здравствуйте!

Суть задачи такая: есть около 10 000 (10 тысяч) продуктов в прайсе в формате XML. Нужно импортировать все продукты в базу данных.
У каждого продукта есть собственный код по которому можно искать в базе. Задача сводится к тому, что по коду продукта нужно смотреть в базе,
есть там уже продукт с таким кодом и если есть, просто обновлять информацию, если нет, то добавлять.

Но есть ограничение: нельзя делать много запросов в базу для выборки, т.е. 10000 запросов SELECT неприемлимо. Выбирать все в массив, тоже не выход, т.к.
в базе может быть около 1000 000 продуктов. Если выбрать все 1000000 записей получим для худшего случая такой расход памяти:
Код

(2 * 255 * 1000000) / 2^20 = 486.374 МБ

UTF-8 может занимать 2 байта, поэтому 2, умножаем на макс. кол-во символов в коде и умножаем на общее кол-во продуктов в базе, после чего получаем
кол-во мегабайт.

Поэтому нужен какой-то алгоритм, который позволит искать продукты по коду с меньшим количеством запросов.

Пример кода продукта: "abcd" - это просто строка длиной до 255 символов.

Можете ли вы посоветовать такой алгоритм или просто подсказать/показать как тут можно поступить?
PM MAIL   Вверх
Akina
Дата 28.4.2011, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Грузим файл на сайт, средствами SQL импортируем его в таблицу и одним запросом получаем необходимые данные.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Lipetsk
Дата 29.4.2011, 08:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


в форме ;)
*


Профиль
Группа: Участник
Сообщений: 180
Регистрация: 28.1.2009
Где: Липецк

Репутация: 2
Всего: 5



Цитата(Hinikato @  28.4.2011,  21:09 Найти цитируемый пост)
нельзя делать много запросов в базу для выборки, т.е. 10000 запросов SELECT неприемлимо

откуда 10000 запросов?
PM   Вверх
Hinikato
Дата 29.4.2011, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.2.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 28.4.2011,  23:52)
Грузим файл на сайт, средствами SQL импортируем его в таблицу и одним запросом получаем необходимые данные.

Akina, можно подробнее, насколько я понял, вы описали кратко саму суть задачи, а не ее решение.

Добавлено через 2 минуты и 21 секунду
Цитата(Lipetsk @  29.4.2011,  08:03 Найти цитируемый пост)
откуда 10000 запросов? 

В цикле мы идем по продуктам, для каждого продукта мы ищем в базе его код, если продукт с таким кодом найден в базе, мы делаем UPDATE, иначе,
делаем INSERT. Прояснило ли это для вас суть задачи?
PM MAIL   Вверх
Akina
Дата 29.4.2011, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 20
Всего: 454



Цитата(Hinikato @  29.4.2011,  13:41 Найти цитируемый пост)
 можно подробнее, насколько я понял, вы описали кратко саму суть задачи, а не ее решение.

Это - решение. Или, если желаете, алгоритм решения.
А если нужна реализация - Вам в другой раздел. В раздел по работе из конкретного ЯП с конкретной СУБД.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
ksnk
Дата 29.4.2011, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 7
Всего: 386



Цитата(Akina @  28.4.2011,  23:52 Найти цитируемый пост)
Грузим файл на сайт, средствами SQL импортируем его в таблицу и одним запросом получаем необходимые данные. 

Вряд ли получится одним запросом для 100000 строк smile Ограничение строки sql-запроса - 64к, imho? Так что запросы на вставку данных все равно придется бить на куски. 

А так - все просто. Строим такую-же временную таблицу, как и таблица товаров, строим запросы "insert ... values" с максимальными количествами товаров и исполняем.
После заполнения временной таблицы - запрос на изменения - один и запрос на вставку - другой.

Разумнее, все-таки, на компьютер клиента, на котором строится XML таблица, поставить скрипт преобразования всего этого добра в SQL, и грузить на сервер именно sql запрос.


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Hinikato
Дата 29.4.2011, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.2.2007

Репутация: нет
Всего: нет



Похоже немного непонятен мой вопрос. Вот краткий псевдокод, чтобы стала понятна суть:
Код

while (product = GetProductFromXML(productIndex)) {
  var productCode = product.GetCode();
  productInDb = FindProductByCodeInDB(productCode);
  if (productInDb == null) {
     InsertProductToDb(product);
  }
  else {
     UpdateProductInDb(product);
  }
  productIndex++;
}

Каждый вызов FindProductByCodeInDB() это один SELECT:
Код

Product FindProductByCodeInDB(code) {
   // Здесь делаем SELECT * FROM product WHERE code = ' + code + ';
  // Возвращаем null или Product
}

Если у нас 10000 продуктов, то получаем 10000 селектов. Как преобразовать это дело можно, чтобы не выбирать все коды в память, а потом в памяти искать. Объясню почему не получится выбрать все 1000 000 кодов из базы одним запросом. Потому что это получится:
Код

(2 * 255 * 1000000) / 2^20 = 486.374 MB

а такой расход памяти недопустим. Поэтому вопрос, как можно это оптимизировать? Я надеюсь может вы подскажете какой алгоритм есть особый который позволяет как-то умно уменьшить кол-во селектов и искать продукт по коду в базе/памяти.

Это сообщение отредактировал(а) Hinikato - 29.4.2011, 15:57
PM MAIL   Вверх
ksnk
Дата 29.4.2011, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 7
Всего: 386



--Не нужно искать товары отдельными запросами.
--Нужно импортировать маловразумительную xml таблицу в базу данных, в отдельную таблицу, специально для этого дела создаваемую.
--Для этого импорта лучше всего подходят длинные и быстрые "insert...values..." запросы. Именно ими оперируют все процедуры импорта-экспорта менеждеров баз данных.
--Кто и где будет делать sql дамп не суть важно, хотя я предпочел бы, чтобы клиент, так как сервер и так занят. Для этого нужно поставить несложный конвертер (можно на php ;) ) на клиентскую машину. Для такого очень удобны фреймворки, которые умеют делать консольные приложения.

После успешного импорта таблицы товаров в новую таблицу на сервере, операция импорта товаров становится достаточно тривиальной.

Это сообщение отредактировал(а) ksnk - 29.4.2011, 16:22


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Hinikato
Дата 30.4.2011, 05:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.2.2007

Репутация: нет
Всего: нет



ksnk, наконец-то, надеюсь, я понял вашу идею, спасибо, умное решение smile

У меня остались некоторые вопросы по той части, о которой вы говорите как о тривиальной.

В результате мы получим две похожих таблицы:
- в первой таблице будут храниться товары для импорта, загруженные из XML,
- во вторую нам нужно будет их перенести. Это как я понял можно сделать SQL запросом, но тут вопрос каким. Ведь он должен решать по-сути ту же саму задачу: обновить те товары, код которых совпадает и вставка тех товаров, код которых не совпадает. Мои вопросы такие:

1. Можно привести хотя бы набросок SQL запроса, чтобы я понял общий смысл?
2. Можно ли это сделать без хранимой процедуры, при этом не забыв, что делать 1000 000 запросов неприемлимо? Или все-таки здесь не обойтись без хранимой процедуры?



Это сообщение отредактировал(а) Hinikato - 30.4.2011, 05:58
PM MAIL   Вверх
almagnit
Дата 30.4.2011, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 283
Регистрация: 3.4.2008

Репутация: нет
Всего: 7



Если productCode является уникальным или первичным ключом то можно пользоваться такими запросами
Код

insert into table (product_code, product_details) values ("abc", "def") ON DUPLICATE KEY UPDATE product_details = "def";

В случае совпадения какого-нибудь ключа, СУБД самостоятельно обработает исключение и выполнит UPDATE для указанных столбцов.
PM MAIL ICQ   Вверх
Hinikato
Дата 30.4.2011, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.2.2007

Репутация: нет
Всего: нет



Цитата(almagnit @ 30.4.2011,  10:25)
Если productCode является уникальным или первичным ключом то можно пользоваться такими запросами
Код

insert into table (product_code, product_details) values ("abc", "def") ON DUPLICATE KEY UPDATE product_details = "def";

В случае совпадения какого-нибудь ключа, СУБД самостоятельно обработает исключение и выполнит UPDATE для указанных столбцов.

almagnit, изящно, спасибо, взял себе как способ одним запросом обновить строку или вставить ее.

Я кажется понял, как можно это сделать:

выбираем коды всех продуктов у которых product_code совпал:
Код

SELECT p1.product_code FROM product1 p1
INNER JOIN product2 p2 ON p1.product_code = p2.product_code
ORDER BY p1.id;

В худшем случае их кол-во будет равно кол-ву импортируемых товаров, таким образом массив не будет превышать 10000 кодов продуктов,
а это равно:
Код

(2 * 255 * 10000) / 2^20 = 4,86 МБ.

Размер такого массива допустимо выбирать в память и искать продукты по коду в нем.

Спасибо ребята за помощь ;) Тема закрыта, если кто-то еще не хочет ее чем-то дополнить.


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.1078 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.