База данных для каталога товаров с несколькими магазинами, иерархическими категориями - PullRequest
0 голосов
/ 27 ноября 2018

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

Идея состоит в следующем: существуетСеть автономных магазинов с несколькими магазинами (~ 10).В каждом магазине есть несколько товаров (~ 100000), которые распределяются между ними, но доступность и цены / скидки различаются.Продукты структурированы в иерархические категории (~ 1000).Некоторые категории могут быть дисконтными.Некоторые нет.Некоторые продукты могут быть только для взрослых.Товары имеют различные атрибуты.

Необходимые запросы:

  • Получить полное дерево категорий (ограничено уровнем вложенности) для данного магазина с товарами, доступными в настоящее время (отфильтрованные по флагу взрослых).
  • Получить некоторое поддерево по заданному идентификатору категории для данного магазина с товарами, доступными в настоящее время.
  • Получить дерево для категорий только со скидкой для данного магазина с товарами, доступными в настоящее время и имеющими скидку.
  • Получение разбитого на страницы списка доступных в настоящее время товаров для данного магазина в данной категории, включая подкатегории, отфильтрованные по взрослым.
  • Получение сведений об одном продукте с полным списком атрибутов.
  • Фильтр товаровпо атрибутам.

Текущее решение построено поверх Oracle Database со следующей схемой:

Таблицы: stores, products, categories (иерархия через MPTT), products_categories (ссылки products и categories), productprices (ссылки stores и products), attributes (ссылки stores), productattributes (ссылки attributesproducts), attributevalues (ссылки productattributes).

Это вроде работает, но начинает работать медленно.Например, запрос для получения категорий с доступными продуктами иногда выполняется менее чем за секунду, а иногда - более 30, в зависимости от данных, импортируемых в настоящее время в базе данных.

Запрос, о котором идет речь:

SELECT "categories".* FROM "categories"
WHERE (
  NOT ("categories"."external_id" = '_reserved' AND "categories"."external_id" IS NOT NULL)
  AND "categories"."is_promo" = 0
  AND "categories"."begins_on" <= to_timestamp('2018-11-27', 'YYYY-MM-DD')
  AND "categories"."ends_on" >= to_timestamp('2018-11-27', 'YYYY-MM-DD')
  AND (EXISTS(
    SELECT U0."id" FROM "productprices" U0
    INNER JOIN "products" U1 ON (U0."product_id" = U1."id")
    INNER JOIN "products_categories" U2 ON (U1."id" = U2."product_id")
    WHERE (
      U2."category_id" = ("categories"."id")
      AND U0."updated_at" >= to_timestamp('2018-11-27 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
      AND U0."store_id" = 42
      AND U0."begins_on" <= to_timestamp('2018-11-27 09:00:00', 'YYYY-MM-DD HH24:MI:SS')
      AND U0."ends_on" >= to_timestamp('2018-11-27 09:00:00', 'YYYY-MM-DD HH24:MI:SS')
      AND (U0."discount" IS NOT NULL OR U1."has_special_offer" = 1)
      AND U1."is_adult" = 0))
  )
)
ORDER BY "categories"."tree_id" ASC, "categories"."lft" ASC

В настоящее время мы собираемся начать миграцию с Oracle Database.Основной базой данных приложения будет Postgres, но для части каталога приложения я хочу взглянуть на другое хранилище.Или, может быть, я должен просто оптимизировать схему / запросы?

В настоящее время существует 15 магазинов, и ~ 4 магазина добавляются ежегодно.Насколько я знаю, никогда не должно быть более 200 000 товаров.С 25 магазинами он ограничивает таблицу цен на 5 000 000 строк в обозримом будущем.

1 Ответ

0 голосов
/ 28 ноября 2018

Из того, что я знаю, несколько миллионов строк в порядке для Postgres.Я бы не стал переходить на какое-либо решение NoSQL.Вместо этого сосредоточьтесь на оптимизации (правильная модель, индексы и т. Д.) И рассортируйте импорт, который вы упомянули (предотвращение длинных блокировок, крупных транзакций и т. Д.).Отправленный вами запрос должен быть легко проиндексирован (используйте частичные индексы на Postgres).Вот что я бы сделал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...