eコマース注文表。価格を節約するか、監査/履歴テーブルを使用しますか?


13

初めてのeコマーススキーマを設計しています。私はしばらくの間このテーマについて読んでいますが、との関係について少し混乱order_line_itemしていますproduct

A productを購入できます。さまざまな詳細がありますが、最も重要なのはunit_priceです。

Anがorder_line_itemへの外部キーがあるproduct_id、購入quantity購入しunit_priceた時点で、顧客が製品を購入します。

私が読んだもののほとんどは、を明示的に追加unit_priceするorder_line_item必要がある(つまり、を介して参照しないproduct_id)と述べています。店舗は将来的に価格を変更する可能性があり、注文レポート、追跡、整合性などを台無しにする可能性があるため、理にかなっています。

私が理解していないことは、なぜunit_price値を直接保存するのorder_line_itemですか?

unit_price変更を記録する監査/履歴テーブルを作成する方が良いproductでしょうか?

ときにorder_line_item作成され、の外部キーproduct_auditテーブルが追加され、価格はそこから(参照によって)取得することができます。

このアプローチを使用することには多くの利点があるように思えます(データの重複、価格変更履歴など)。このアプローチを使用するeコマーススキーマの例に出くわしていませんが、何か不足していますか?

UDPATE:私の質問はSlowly Changing Dimensionに関連しているようです。ただし、緩やかに変化するディメンションはデータウェアハウスとOLAPに関連しているため、私はまだ混乱しています。それで、Slowy Changing Dimensionタイプをメインのビジネストランザクションプロセスデータベース(OLTP)に適用できますか?私は多くの概念を混ぜているのだろうか、いくつかのガイダンスを大いに感謝します。


私は実際に両方を行います:販売価格をorder_line 保存し、製品価格の履歴を保存します。両方が異なる目的に役立つからです。販売価格を保存すると、注文のクエリがはるかに簡単かつ迅速になります。一方、販売されていない製品についても古い価格を取得したい場合があります。
a_horse_with_no_name 14

確かに注文照会を簡単にすることは、毎回最終価格を節約する唯一の要因ではありません。結局、リレーショナルデータベースです。クエリはそれほど難しくありません。
Gaz_Edge 14

3
注文ラインに販売価格を保存することは「非リレーショナル」ではありません(そして、私の意見では、販売価格は注文ラインの直接的な属性であるだけでなく、正規化されていると思います)。リレーショナルデータベースを使用する技術は、限界を知ることです。100の製品と1日に5件の注文があるショップを運営している場合、古い価格の保存と取得は問題になりません。あなたは何百万もの製品で市場を実行している場合は、ディーラーや毎分のオーダーのhundresの何千人も、その歴史を照会することになる問題です。
a_horse_with_no_name 14

履歴価格はどこに保存しますか?私が読んでいるものから、2つのデータベースが必要です。OLTPに1つ、OLAPに1つ。履歴はOLAPに含まれますか?
Gaz_Edge 14

回答:


10

確認したとおり、注文に価格を保存すると、技術的な実装が容易になります。しかし、これが有益なビジネス上の理由がいくつかあります。

Webトランザクションに加えて、多くの企業は他のチャネルを介した販売をサポートしています。例:

  • 電話で
  • 「外出中」の販売代理店
  • 物理的な場所(例:ショップ、オフィス)

これらの場合、取引が行われた後のある時点で注文がシステムに入力される場合があります。これらの状況では、どの履歴価格レコードを使用すべきかを正確に特定することは困難または不可能になる可能性があります。単価を注文に直接保存することが唯一の実行可能なオプションです。

複数のチャネルは、多くの場合、別の課題をもたらします-同じ製品の異なる価格。電話注文の追加料金は一般的であり、一部のお客様は割引を交渉する場合があります。製品スキーマ内のすべてのチャネルのすべての可能な価格を表すことができる場合がありますが、これをオーダーテーブルに組み込むことは(非常に)複雑になる可能性があります。

交渉が許可されている場所であればどこでも、価格履歴を合意した注文価格にリンクすることは非常に困難になります(エージェントが非常に狭い交渉制限を持たない限り)。注文自体に価格を保存する必要があります。

Webトランザクションのみをサポートし、比較的単純な価格設定構造を持っている場合でも、克服すべき興味深い問題がまだあります。価格の上昇を機内トランザクションでどのように処理する必要がありますか。ビジネスは、顧客が追加料金を支払う必要があると主張していますか、それとも元の価格を尊重していますか(製品がバスケットに追加されたとき)?後者の場合、技術的な実装は複雑です。セッションで価格バージョンを正しく維持する方法を見つける必要があります。

最後に、多くの企業が非常に動的な価格設定を使用し始めています。特定の製品に1つの固定価格がない場合があります。時刻、製品の需要などの要因に基づいて実行時に常に計算されます。これらの場合、価格はそもそも製品に対して保存されないかもしれません!


3

私が見たいくつかの実用的なポイントを追加します。

  1. 製品は一時的なものです。

    彼らが今日意味することは、彼らが1年前を意味するために使用したものと同じではないかもしれません。同じskuコード(したがってproduct_id)は、異なる段階で製品の異なるバリアント/種類を参照する場合があります。

    誰もが目前のすべての懸念を理解しているわけではありません。したがって、ユーザーは自分の無知から新鮮な製品を作成する代わりに、元の製品の属性を変更することができます。多くの場合、これはユーザーの計画が原因で発生する可能性があります(ちょっと!100個のSKUしか持てないので、計画をアップグレードするのではなく、古いSKUを変更し続けないでください)。 、製品が永遠に同じことを意味することはありません。

  2. 注文および出荷条件に基づいて異なる価格

    ユーザー@Chrisが述べたように、異なるシナリオでは異なる価格が適用される場合があります。

    ほとんどのカートでは、少なくとも3つの異なるフィールド(単価、割引額、割引価格)が保存されています。より高度なものでは、さらに2つ表示されます-税込みの単価、税込みの割引価格。配送方法の料金と追加の支払い方法の料金を説明するフィールドがさらにいくつかあります。税率は、州、製品、国、配送方法などによって異なり、その他の費用額も異なります。同様に、割引は地理、プロモーション、販売時期などによって異なる場合があります。したがって、注文レベルでのみ取得できる情報があり、この結合された情報は製品テーブルのデータだけから生成することはできません。

  3. 関心事の分離

    さまざまなチームがデータのさまざまな部分を制御できるように、多くのカートが何らかの方法で実装されています。注文システムを管理する人は、すべての製品の在庫、異なる時点での価格、特定のSKUの代替品などを常に把握する必要はありません。注文データとともに製品関連データを保持すると、懸念の分離を達成するのに役立ちます。異なるチームがシステムの異なる部分を管理する場合、これは開発段階でも当てはまります。

  4. 複数のシステムにわたる拡張容易性

    多くの場合、注文管理システム、ルールエンジン、カタログエンジン、コンテンツ管理システムはすべて、独自の個別のシステムとして構築/維持されます。これにより、さまざまな負荷条件を最適化し、各システムに特化したインテリジェンスを生成できます。そのため、あるシステムは、別のシステムからの情報が利用できないため、身代金を免れることができません。

  5. 開発と実行時間の短縮

    ここでは「開発時間」という用語を使用しましたが、「デバッグ時間」を使用する方が適切です。新しい開発が行われるたびに、独自の複雑さを追加することなく必要なデータが利用可能であれば、デバッグサイクルが比較的短くなるため、より高速になります。

    半年前の特定の月に毎日提供される割引のオンデマンドレポートを生成するように求められたとします。元の価格、注文、注文項目の詳細とともに1-2テーブルの割引価格がある場合、これは非常に簡単です。ただし、別のテーブルから価格を取得し、別のテーブルから該当する割引を取得して、詳細を把握する必要がある場合、開発時間と実行時間の両方が長くなります。

優れた設計では、現在と同じように、将来も最大限に最適化する必要があります。


2

最終的にストレージのコストが高くなる可能性がありますが、何らかの理由で監査証跡が壊れたり、管理者が適切な安全性を無効にしたりする場合、販売の関連するすべての詳細をトランザクション自体に格納することを好みます使用される通貨:使用通貨、単価、数量、適用される税金、およびその価値など。すべて利用可能です。通常、私はそれをXMLとして保存するので、販売ごとに柔軟に対応できます。


編集:上記の簡単なコメント、以下のフォローアップコメント、および上記の@a_horse_with_no_nameに触れた内容を拡大するには、トランザクションデータの冗長性が重要であるだけでなく、大規模にも必要です。

私はあなたがOOPを使用して構築していると仮定しているので、おそらくトランザクションオブジェクトと、すべてを包含する製品オブジェクトおよび/または価格オブジェクトが必要です。私自身の個人的な経験では、私は私の歴史の中で冗長であることを好みます、ストレージは比較的安いです。

私たちが行ったのは、既存のRDBMSまたはNOSQLキー値ストアのフレーバー(または、さらによく、socketsocketやmemcacheなどの接続のようなNoSQLを許可するRDBMS)の使用を容易にするオブジェクト履歴を作成することです。そのようにして、すべての詳細と価格を1か所で簡単かつ迅速に変更できます。深刻な場合は、DIFFを使用してストレージに保存し、変更を前方にのみ保存することもできますが、独自の警告があります。これで履歴が管理され、シリアル化されたオブジェクトの利点は、システムがオブジェクトを保存されたオブジェクトとして戻すことができることです。それが歴史の面倒を見る。

私の提案に関しては、税金、通貨などの取引の詳細を取引自体に保存することは、それらの詳細を他の場所で探す必要がないことを意味します。適切と思われるさまざまなデータ。スナップショットへの迅速なアクセスが得られ、冗長で検証可能なレコードの利点が追加されます。

それは価値がある、私を信じて!


削除される可能性があるため、使用しないと言っても意味がありません。任意のデータをオーバーライドできます。いずれの戦略は、バックアップを維持する必要があります
Gaz_Edge

@Gaz_Edgeこれらは相互に排他的ではありません。監査証跡を利用し、詳細をトランザクションとともに保存できます。この場合の冗長性は正当化されます。この重要な問題を単一障害点にさらさないでください。この例では、オブジェクトタイプ(この場合はトランザクションや製品など)ごとに履歴を作成しようとするのではなく、履歴メカニズムとして集中オブジェクトストアを使用します。履歴にはトランザクションオブジェクト全体の両方がありますが、レコード自体にはすべての最も重要な詳細があります。それは完全に歴史の製品オブジェクトの脇にあります。
oucil 14

注文に関するレポートを実行する場合はどうなりますか?いくつの製品xが購入されたかなど?または、yを超える注文数は?XML手段として保存あなたは、私が間違えてる場合を除き、データを照会する能力を失う
Gaz_Edge

@Gaz_Edge真実ではありません。MySQLを使用している場合SELECT ExtractValue(field_name, '/x/path/');、特定の通貨でのすべてのトランザクション、特定の最小税額を持つすべてのトランザクションなどをフィルタリングできます。オブジェクト履歴から大規模なレポートを作成できます。大規模なレポートの場合、elasticsearchBigDataスタイルのレポートを備えたサーバー/インスタンスをセットアップでき、数百万のドキュメントに簡単に拡張できます。
oucil

@Gaz_Edge言及する必要があります、あなたが話しているレポート(価値を超える購入、製品の販売など)は一般的なレポートであり、処理を高速化するために値をトランザクションレコードに格納する必要があります。重要であるが、必ずしも報告されていないものは、多くの場合XMLに含まれます。スナップショットデータは、実際には2つのことのみに対応しています。1。緩やかに変化するディメンションの問題、2。顧客から苦情があった場合の検証と比較。毎日使用するためではありません。
oucil 14

1

私の投票は、広告申込情報に単価を保存し、別のテーブルで製品の価格履歴を追跡することです。これを正当化する理由は、柔軟性を高めるためです。

価格体系が厳格で明確に定義されていて、@ Chris Saxonが上記で述べたバリエーションを許可していない場合でも、それが常にそのようになることを安心しますか?自信があるとしても、なぜ自分を隅にペイントするのですか?これを広告申込情報の詳細に保存するのは良い考えだと思います。なぜなら、それを個別に保持する説得力のある理由を考えることができないからです。

価格履歴を保存することに関しては、アイテムの価格に変化があり、誰もそれを購入していない可能性があるため、個別に保存することには明確な価値があります。これは、価格の変更が効果的でないかどうかを知るのに役立つ情報です。前述のように、これはデータウェアハウスシナリオでのタイプ2の緩やかに変化するディメンションの古典的な使用例です。通常、製品テーブルの価格変更はすべてキャプチャされ、更新された価格とこの変更がいつ行われたかを示すタイムスタンプとともに新しい行がディメンションテーブルに追加されます。前の行の終了日は更新され、有効な価格ではなくなったことを示します。したがって、1つのアプローチは、データウェアハウスでこのタイプの変更を追跡することです。

ただし、OLTP eコマースデータベースの設計と同時にデータウェアハウススキーマとETLプロセスの設計に関心がない場合は、この履歴をeコマースデータベースに確実に取り込むことができます。これは、製品テーブルからハングアップし、製品のそのバージョンが有効であった開始日と終了日を含む別のproduct_auditテーブルを作成することで説明したように実行できます。開始日と終了日をテーブルに追加して、現在アクティブな製品を示すことにより、製品テーブル自体で行うこともできます。ただし、製品の数、会社が受ける数または価格の変更によっては、これにより製品テーブルが意図したよりもはるかに大きくなり、クエリパフォーマンスの問題が後で発生する可能性があります。

最後に、ラインアイテムの実際の単価から価格設定履歴を分離すると、その時点でリストされている価格を上回るまたは下回る価格で製品が販売された時期を確認するための他の分析機会が確実に得られます。


答えてくれてありがとう。私が行っている戦略は、本ごとにOLTPを設計することだと思います。実際に、レポート用のデータウェアハウスを持つというアイデアが好きです。追加の作業(新しいスキーマの作成)が追加されますが、スキーマはOLAPに合わせて調整できます。丸穴に四角い釘をはめ込もうとするシナリオを回避するようなもの。
Gaz_Edge 14

@Gaz_Edge:私の新しいプロジェクトを決定するという点では、同じような状況にあります。あなたが1年前に取った設計アプローチについてのあなたの考えを共有してください。うまくいきましたか?
コーダーアブソリュート

@CoderAbsolute私の元のソリューションは、非常に「データベース」指向でした。私のアプリケーションは現在、サービス指向アーキテクチャを中心にしています。密結合されたものではなく、多くの小さな分離されたデータベーススキーマがあります。1つの大規模なスキーマ間で3Nを実行する必要がなくなりました。そこで、単価を直接注文に追加するだけです。過去の製品価格の変更を保持することは、ビジネス要件ではなかったため、現在ではなくなりました。お役に立てば幸いです。
Gaz_Edge

0

私は、注文に関連する情報(コンテキスト)をまとめるという第一の考えに完全に同意します。ちょっとした注意点として、このような状況は、アプリケーションをデータベース中心に設計しているときにのみ発生し、すべてが大きなファットデータベースを中心に展開することに注意してください。問題の領域を別の角度から見て視点を切り替えると、順序がアプリケーションのライフサイクルにおける非常に特殊なイベントのスナップショットであることが明確にわかります。コンテキストに基づいて問題を処理すると、データベースの問題が二次的になり、誰もがクエリの作成やレポートの作成を恐れる複雑さがドメインモデルでシームレスに処理されます。


いくつかの小さな例は、あなたの答えをはるかに理解しやすくします。特に、「順序は、アプリケーションのライフサイクルにおける非常に特別なイベントのスナップショットをキャプチャしたもの」のような文です。
dezso 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.