web-dev-qa-db-ja.com

多対多の関係のためのスタースキーマの設計

本番データベースからDWスタースキーマ設計を構築するための手順/ルールは何ですか。具体的には、多対多の関係をどのように処理しますか。

多対多の関係を含む基本的なデータを取得し、正規化された本番データベースにアクセスする方法を理解しています。

例えば:

テーブルProduct EntityPromotionEmployeeを指定して販売トランザクションを処理する場合、最初のステップはテーブルSaleTransactionを作成することです。

SaleTransaction
- TransactionID
- ProductID
- EmployeeID
- SellingDateID
- Quantity
- SaleAmount
- PromotionID

Promotionエンティティは次のようになります。

Promotion
- PromotionID
- ProductID
- DiscountAmount

ただし、販売トランザクションごとに1つの製品と1つのプロモーションしか許可されません。 1つ以上の製品と0個以上のプロモーションを許可したいので、

  • PromotionIDProductIDQuantity、および(いくつかのビジネスルールで要求されない限り)SaleAmountSaleTransactionから削除します

  • SaleTransactionDetailを作成します。

    - DetailID
    - TransactionID
    - ProductID
    - Quantity
    - SaleAmount
    
  • SaleTransactionPromotionを作成します:

    - TransPromoID
    - PromotionID
    

本番DB設計をDWスタースキーマ設計に移行するための同等の手順は何ですか?

2
hqt

多対多のテーブルは、通常「ブリッジテーブル」で処理されます。これは、トランザクションデータベースで使用するような多対多のテーブルの別の名前です。最初のテーブルへのFKの1つの列、2番目のテーブルへのFKの1つの列、そしておそらく1つまたは2つの列ハウスキーピングフィールド用。

また、ブリッジテーブルのWeightフィールドに、1を各販売のエントリ数で割った値を設定することもできます。これにより、複数のプロモーションがあった注文の二重カウントを避けたい場合に、SUM(Weight)ではなくCOUNT(*)を計算できます。

提案されたスキーマはそのままで良いですが、少し改善できると思います。 2つのことが頭に浮かびます。 1つは、通常、SalesTransactionsSalesTransactionDetailsを1つのテーブルに折りたたむことです。これにより、顧客IDなどの冗長性が導入され、OLTP本能が軽快になります(正規化されたデータベースからデータウェアハウジングへの移行はパラダイムシフトです!)。ただし、この場合は価値があります。すべての売り上げを1つのテーブルにまとめると、結合が簡素化され、多くのデータベースでは、ビットマップインデックスを使用することを通知します。ウェアハウスでは、テーブルスキャンを実行しなければならないことがよくありますが、ファクトテーブルは非常に狭く、メモリに収まります。

したがって、3つのテーブルSalesPromotions、およびSalesPromotionsがあります。後者は適用されない可能性がある最終性を意味するため、「販売」ではなく「注文」を検討する場合があります。システムに、発注されたが出荷されていない、またはクローズされていない注文が含まれている場合、より一般的な用語が意味をなします。それは不自然なことですが、名前の付け方について慎重に考えることは決して害にはなりません。

CREATE TABLE Orders
    -- IDs/dimensions:
    OrderID
    EmployeeID
    ProductID
    -- Date dimensions: date placed, date contract signed, date shipped, etc.
    -- Metrics: quantity, gross price, net price, extended price
    -- Attributes: is taxable, currency code, business key

CREATE TABLE Promotions
    PromotionID
    -- Date dimensions: date effective, date expires
    -- Metrics: fixed amount, percentage amount
    -- Attributes: name, type

CREATE TABLE OrderPromotions
    OrderID
    PromotionID
    Weight

ExtendedPriceは、値を格納するのではなく、計算列にすることができます。属性がOrdersテーブルを膨らませ始める場合は、「 ジャンクディメンション 」を検討してください。

ProductIDPromotionsに含めることもできますが、これはプロモーションが1つの製品にのみ適用される場合に限られます。たとえば、特定のラインアイテムではなく注文全体に適用されるいくつかのプロモーションがありますか?本日のプロモーションは商品コードABC1に適用されますが、価格変更後のABC2には明日適用されますか?

2つ目の注意点はIDです。ソースシステムのIDに依存するのではなく、データウェアハウスで合成キー(SK)を使用することを強くお勧めします。理由はいくつかあり、これはDBA.StackExchangeの他の場所で説明されていますが、手に負えません:

  1. 多くの場合、SKの32ビットまたは64ビットの整数は、ソースシステムの注文IDまたは顧客ID(たとえば、144ビットのSalesforce IDまたは他の長い英数字のID)よりも狭くなります。これにより、テーブルが狭くなり、セカンダリインデックスが狭くなり、スキャンが高速になります。
  2. ソースシステムでの衝突を回避できます。ある日マーケティングが去年とは関係のない何かのためにプロダクトキーABC123を使用することを決定した場合、それらに2つの異なる合成キーを与えることができます。
  3. 特に、会社が別のビジネスを買収した場合、そのIDが使用していたデータタイプと一致しないことがあります。それらを共通のセットにマップし、衝突を処理する必要があります。そのためのインフラストラクチャを最初から持っているのが最善です。
  4. レポートに関連しているがトランザクションシステムでは処理されない特定の意味にマジック値を使用できます。たとえば、「N/A」には常にSKs -1を使用し、「不明」には0を使用します。たとえば、Customers.FirstOrderSKフィールドには、注文したことがない顧客の場合は-1、注文したがまだ特定の情報がまだ入手できない顧客の場合は0が入力されます。レポートは、NULL値を処理する特別なロジックを配置する必要なく、これを反映できます。

プロモーションなしの注文の「ダミーレコード」を含めることにより、ブリッジテーブルの合成キーを利用できます。 PromotionIDに-1を入力して、プロモーションが適用されなかったことを示します。これで、データの消費者は、定価で販売された注文をフィルタリングできます。

5