Я создаю свою первую схему электронной коммерции. Я читал вокруг предмета на некоторое время, и я немного запутался об отношениях между order_line_item
иproduct
А product
можно было купить. В нем есть разные детали, но самое главное unit_price
.
У order_line_item
него есть внешний ключ к product_id
купленному, quantity
приобретенному и тому unit_price
моменту, когда покупатель приобрел продукт.
Большая часть того, что я прочитал, говорит о том, что объект unit_price
on order_line_item
должен быть явно добавлен (т.е. не указан через product_id
). Имеет смысл, так как магазин может изменить цену в будущем, что испортит отчеты о заказах, отслеживание, целостность и т. Д.
Вещь, которую я не понимаю, - зачем напрямую сохранять unit_price
значение в order_line_item
?
Не лучше ли создать таблицу аудита / истории, которая документирует unit_price
изменение product
?
Когда order_line_item
создается, product_audit
добавляется внешний ключ таблицы, и цена может быть получена (по ссылке) оттуда.
Мне кажется, есть много положительных сторон в использовании этого подхода (меньшее дублирование данных, история изменения цен и т. Д.), Так почему же он не используется чаще? Я не встречал пример схемы электронной коммерции, которая использует этот подход, я что-то упустил?
UDPATE: Похоже, мой вопрос касается медленно меняющегося измерения . Я все еще в замешательстве, поскольку медленно изменяющееся измерение относится к хранилищу данных и OLAP. Так можно ли применять типы медленного изменения размеров к моей основной базе данных процессов бизнес-транзакций (OLTP)? Мне интересно, если я смешиваю много понятий, был бы очень признателен за некоторые рекомендации.
источник
Ответы:
Как вы уже определили, хранение цены заказа облегчает техническую реализацию. Есть ряд деловых причин, почему это может быть полезным, хотя.
В дополнение к веб-транзакциям многие компании поддерживают продажи через другие каналы, например:
В этих случаях заказ может быть введен в систему через некоторое время после совершения транзакции. В этих обстоятельствах может быть трудно или невозможно правильно определить, какая историческая запись цены должна использоваться - хранение цены за единицу непосредственно в заказе является единственным возможным вариантом.
Несколько каналов часто создают другую проблему - разные цены на один и тот же продукт. Доплаты за телефонные заказы распространены - и некоторые клиенты могут договориться о скидке. Возможно, вы сможете представить все возможные цены для всех каналов в схеме вашего продукта, но включение этого в ваши таблицы заказов может стать (очень) сложным.
Везде, где разрешены переговоры, становится очень трудно связать историю цен с согласованной ценой заказа (если только у агентов нет очень узких пределов переговоров). Вам нужно хранить цену на самом заказе.
Даже если вы поддерживаете только веб-транзакции и имеете относительно простую структуру ценообразования, все еще есть интересная проблема, которую нужно преодолеть - как следует учитывать повышение цен в полетных транзакциях? Настаивает ли компания на том, что покупатель должен платить повышение или соблюдает первоначальную цену (когда товар был добавлен в корзину)? Если это последнее, то техническая реализация сложна - вам нужно найти способ убедиться, что вы поддерживаете ценовую версию в сеансе правильно.
Наконец, многие компании начинают использовать высокодинамичные цены. Для данного продукта может быть не одна фиксированная цена - она всегда рассчитывается во время выполнения на основе таких факторов, как время суток, спрос на продукт и т. Д. В этих случаях цена не может быть сохранена против продукта в первую очередь!
источник
Я добавлю некоторые практические моменты, которые я видел.
Продукты переходные.
То, что они могут обозначать сегодня, может не совпадать с тем, что они использовали для обозначения год назад. Один и тот же код sku (и, следовательно, product_id) может ссылаться на разные варианты / виды продукта на разных этапах.
Не все понимают все проблемы под рукой; следовательно, пользователь может изменить атрибуты исходного продукта вместо создания нового из своего собственного невежества. Много раз, это могло произойти из-за плана, на котором работает пользователь (эй! У меня может быть только 100 sku, так почему бы не продолжать менять старые, вместо того, чтобы обновлять план) Итак, вы видите, во многих тележках продукт никогда не будет означать одно и то же навсегда.
Различные цены в зависимости от заказа и условий доставки
Как отметил пользователь @Chris, в разных сценариях могут применяться разные цены.
В большинстве тележек хранится не менее 3 различных полей - цена за единицу, сумма скидки и цена со скидкой. В более продвинутых вы найдете еще 2 - цена за единицу с налогом, цена со скидкой с налогом. Вы можете найти еще пару полей для описания стоимости доставки и дополнительных платежей. Налоговые проценты могут варьироваться в зависимости от штата, продукта, страны, способа доставки и т. Д., Как и другие виды затрат. Точно так же скидки могут варьироваться в зависимости от географии, рекламных акций, времени продажи и так далее. Следовательно, есть информация, которую можно получить только на уровне заказа, и эта объединенная информация не может быть сгенерирована из данных только в таблице продуктов.
Разделение проблем
Многие корзины реализованы таким образом, что разные команды могут контролировать разные части данных. Кто-то, кто управляет системой заказов, не всегда должен знать, какие все товары есть в наличии, какие цены были в разное время, какие есть альтернативы для данного артикула и так далее. Хранение данных, связанных с продуктом, вместе с данными заказа помогает достичь разделения интересов. Это также может быть верно на этапах разработки, если разные команды управляют разными частями системы.
Более простая масштабируемость для нескольких систем
В большинстве случаев Система управления заказами, Механизм правил, Механизм каталогов, Система управления контентом создаются и обслуживаются как отдельные системы. Это помогает оптимизировать для различных условий нагрузки и генерировать специализированный интеллект для каждой системы. Таким образом, одна система не может быть выкуплена из-за отсутствия информации из другой системы.
Более быстрое развитие и время выполнения
Я использовал здесь термин «время разработки», хотя использование «времени отладки» было бы более подходящим. Всякий раз, когда происходит какая-либо новая разработка, будет быстрее, если необходимые данные будут доступны без добавления собственной сложности, потому что тогда будут сравнительно меньшие циклы отладки.
Представьте, что вас попросили создавать отчеты по требованию для скидок, предлагаемых на ежедневной основе в течение определенного месяца полгода назад. Если у вас есть первоначальная цена, цена со скидкой в 1-2 таблицах вместе с заказом, подробностями заказа, это довольно просто. Однако, если вам нужно пойти и получить цены из другой таблицы, а затем применить скидки из другой таблицы, а затем выяснить детали, время разработки и выполнения будет выше.
Хороший дизайн должен пытаться оптимизировать столько же для будущего, сколько и для настоящего.
источник
Это может в конечном итоге стоить дороже при хранении, но я предпочитаю разместить все соответствующие детали продажи вместе с самой транзакцией, так что если по какой-либо причине наш контрольный журнал будет поврежден или администратор переопределит меры безопасности на месте, детали продажа, такая как: используемая валюта, цена за единицу, кол-во, применяемые налоги и стоимость, к которой они пришли и т. д. Я обычно храню это как XML, так что он может быть гибким от продажи до продажи.
РЕДАКТИРОВАТЬ: Чтобы расширить то, что я кратко сказал выше, в своем последующем комментарии ниже, и то, что @a_horse_with_no_name затронуло выше, избыточность данных транзакций не только важна, но и необходима в масштабе.
Я предполагаю, что вы строите с использованием ООП, и поэтому у вас, скорее всего, должен быть объект транзакции и либо всеобъемлющий объект продукта, и / или объект цены. По своему личному опыту, я предпочитаю быть многословным в своей истории, хранилище относительно дешевое.
Мы создали историю объектов, которую вы можете упростить, используя существующую RDBMS или некоторую разновидность хранилища значений ключей NOSQL (или, что еще лучше, RDBMS, которая позволяет NoSQL-подобным соединениям, таким как handlersocket или memcache), и мы сохраняем историю объектов Таким образом, каждая деталь и изменение цены в одном месте легко и быстро доступны. Если вы серьезно, вы можете даже использовать DIFF, чтобы сэкономить на хранилище и сохранить изменения только вперед, хотя у него есть свои предостережения. Это должно заботиться о вашей истории, и преимущество сериализованных объектов заключается в том, что ваша система сможет / сможет восстановить их как объекты, которые они хранили. Это заботится об истории.
Что касается моего предложения, хранение деталей транзакции, таких как налоги, валюта и т. Д., В самой транзакции означает, что вам не нужно искать другие детали в другом месте, ваш объект транзакции будет знать о его свойствах, и ваши представления могут позаботиться о представлении. переменные данные, как вы считаете нужным. Вы получаете быстрый доступ к снимку и получаете дополнительное преимущество избыточных и проверяемых записей.
Оно того стоит, поверь мне!
источник
SELECT ExtractValue(field_name, '/x/path/');
возможность фильтровать такие вещи, как все транзакции в определенной валюте или все транзакции с определенной минимальной налоговой стоимостью или что-то еще. Отчеты большего масштаба могут быть сделаны из истории объекта. Для более масштабных отчетов вы можете настроитьelasticsearch
сервер / экземпляр, который имеет отчеты в стиле BigData, и он легко масштабируется во многие миллионы документов.Мой голос - хранить цену за единицу для вашей позиции и отслеживать историю цен на ваши продукты в отдельной таблице. Я оправдываю это дополнительной гибкостью.
Даже если ваша структура ценообразования жесткая и четко определенная и не допускает изменений, упомянутых выше @Chris Saxon, вам удобно, что так будет всегда? Даже если вы уверены, зачем рисовать себя в углу? Я думаю, что было бы неплохо сохранить это в деталях позиции, потому что я не могу придумать вескую причину, чтобы отделить ее.
Что касается хранения вашей истории цен, есть определенная ценность в хранении этого отдельно, поскольку могут быть изменения в цене товара, и никто не купил его. Это определенно была бы полезная информация, чтобы знать, было ли изменение цены неэффективным. Как вы упомянули, это классический вариант использования медленно изменяющегося типа 2 в сценарии хранилища данных. Обычно любое изменение цены в вашей таблице продуктов будет зафиксировано, и в таблицу измерений будет добавлена новая строка с обновленной ценой и отметкой времени, указывающей, когда произошло это изменение. В предыдущей строке будет обновлена дата окончания, чтобы указать, что она больше не является эффективной ценой. Поэтому одним из подходов будет отслеживание изменений такого типа в хранилище данных.
Однако, если вы не хотите заниматься разработкой схемы хранилища данных и процесса ETL одновременно с разработкой базы данных электронной торговли OLTP, то эта история, безусловно, может быть сохранена в нашей базе данных электронной торговли. Это можно сделать, как вы описали, создав отдельную таблицу product_audit, которая свисает с таблицы продуктов и содержит даты начала и окончания, когда действовала эта версия продукта. Это также можно сделать в самой таблице продуктов, добавив даты начала и окончания в таблицу, чтобы указать, какой продукт в настоящее время активен. Однако, в зависимости от количества продуктов и количества или изменений в ценах, которые претерпевает ваша компания, это может сделать вашу таблицу продуктов намного больше, чем предполагалось, и впоследствии может вызвать проблемы с производительностью запросов.
Наконец, отделение вашей истории ценообразования от фактической цены за единицу в позиции может, безусловно, дать некоторые другие аналитические возможности, чтобы увидеть, когда продукт был продан по цене, которая была выше или ниже указанной цены в то время.
источник
Я полностью согласен с основной идеей сохранения информации (контекста), относящейся к порядку. Небольшое замечание: такая ситуация возникнет только тогда, когда вы разрабатываете свое приложение, ориентированное на базу данных, и все вращается вокруг большой жирной базы данных. Если вы измените свою точку зрения, взглянув на проблемную область под другим углом, вы четко заметите, что порядок - это снимок очень особенного события в жизненном цикле вашего приложения. Когда вы решаете проблемы в зависимости от контекста, проблемы с базой данных становятся второстепенными, а сложности, которых все боятся запрашивать и создавать отчеты, будут беспрепятственно решаться в доменной модели.
источник