Я ищу помощи в выборе наилучшей базы данных, будь то реляционной или нет, а также наилучшей схемы для данной задачи.
Идея состоит в следующем: существуетСеть автономных магазинов с несколькими магазинами (~ 10).В каждом магазине есть несколько товаров (~ 100000), которые распределяются между ними, но доступность и цены / скидки различаются.Продукты структурированы в иерархические категории (~ 1000).Некоторые категории могут быть дисконтными.Некоторые нет.Некоторые продукты могут быть только для взрослых.Товары имеют различные атрибуты.
Необходимые запросы:
- Получить полное дерево категорий (ограничено уровнем вложенности) для данного магазина с товарами, доступными в настоящее время (отфильтрованные по флагу взрослых).
- Получить некоторое поддерево по заданному идентификатору категории для данного магазина с товарами, доступными в настоящее время.
- Получить дерево для категорий только со скидкой для данного магазина с товарами, доступными в настоящее время и имеющими скидку.
- Получение разбитого на страницы списка доступных в настоящее время товаров для данного магазина в данной категории, включая подкатегории, отфильтрованные по взрослым.
- Получение сведений об одном продукте с полным списком атрибутов.
- Фильтр товаровпо атрибутам.
Текущее решение построено поверх Oracle Database со следующей схемой:
Таблицы: stores
, products
, categories
(иерархия через MPTT), products_categories
(ссылки products
и categories
), productprices
(ссылки stores
и products
), attributes
(ссылки stores
), productattributes
(ссылки attributes
)и products
), 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 строк в обозримом будущем.