各注文には固有のSalesOrderNumber
があります。注文はさまざまなPartID
番号で構成され、それぞれにOrderQuantity
番号が関連付けられています。
現在、モデルには次の表があります。
このテーブルを次のように2つのテーブルに分割する必要があるかどうか疑問に思っています。
これにより、Order
テーブルにはSalesOrderNumber
ごとに1行のみが残りますが、これが正規化の観点から必要かどうかはわかりません。どちらの取り決めも2NFを満たすべきだと思われます。 3NFとBCNFについてはまだ少し不安定です。
テーブルのサンプルは次のようになります。12345のSalesOrderNumber
に関連する列のみが表示されます。
SalesOrderNumber PartID OrderQuantity
12345 1a 1
12345 2b 2
12345 3c 43
正規化の目的は、更新の異常を取り除くことです。具体的には、単一のファクトを変更すると、1行の1列のみが変更されます。たとえば、ShippingDestinationが変更された場合、これが提案された設計にどのように適用されるかを検討してください。
最初の設計では、1つのSalesOrderNumberに複数の行があり、それぞれに独自のPartIDがあるため、複数の行が変更される可能性があります。 2番目のデザインでは、単一の行のみが更新されます。したがって、2番目の設計はより正規化されています。
別の観点から、依存関係-どの値が一斉に変化するかを確認できます。最初の設計では、ある行から同じSalesOrderNumberを持つ別の行に移動すると、ShippingDestinationはDueDateと同じになります。ただし、OrderQuantityはこれら2つの行の間で異なります。したがって、OrderQuantityは、SalesOrderNumberだけではなく、PartIDについても知る必要があります。 2つの異なる依存関係があるため、2つの異なる正規化されたテーブル。 (機能的な依存関係/依存関係の分解には他にもありますが、それがその要点です。)
2NFは「パーツキーの依存関係」について話します。キーのすべての列がすべての非キー列の値を決定するために必要かどうか。最初の設計を見ると、(SalesOrderNumber、PartID)の複合キーがあります。特定のSalesOrderNumberを持つ1つの行から同じ番号を持つ次の行に移動すると、一部の列(たとえば、ShippingDestination)は常に同じになります定義により。 PartIDはキーにありますが、ShippingDestinationの値を決定するために必要ではありません。したがって、最初の設計は2NFではありません。
3NFは、「推移的な依存関係」-キーが変更されたため、または別の非キー列の値が変更されたために列の値が変更されたかどうかについて話します。 2番目の設計が3NFであるかどうかを示す実際のビジネスルールについては十分に理解していないため、デモ用のシナリオを作成します。顧客が所属できるチャネルは1つだけだとします。 Orderの1つの行から次の行に移動すると、CustomerNumberとChannelの両方の値が変化することがわかります。ただし、SalesOrderNumberが異なるためではなく、CustomerNumberが異なるため、チャネルの値が変更されます。チャネルは、CustomerNumberによって(つまり推移的に)SalesOrderNumberによって異なります。私の作成したシナリオでは、チャネルをOrderからCustomerNumberをキーとする新しいテーブル(Customer)に移動する必要があります。
BCNFに違反するには、テーブルに少なくとも1つの列を共有する複数の候補キーが必要です。どちらの設計にもこれがないため、3NFに入ると、設計はBCNFにも含まれます。
はい、テーブルを分割します。
正規化はすでに十分に説明されています。
Clustered Index
は、
Selectivity十分に選択的である必要があります。where句で使用する場合は、1行または2行を返す必要があります。つまり、行全体の1%または2%を返す必要があります。
注文表
SalesOrderNumber varchar(15)がnullではない
OrderDetail TABLE
OrderDetailid int identity(1,1)
他の表では、Orderid
をFK
ではなくSalesOrederNumber
として参照しています。 OrderID
で内部的にすべてを処理します。
SalesOrderNumber
はBizにサービスを提供するためにあります。要件。
でもOrder detail
テーブルほとんどの行はOrderID
を使用して取得されます
したがって、Orderid
はCLUSTERED INDEX
。また、OrderID
は増加し続けているため、CLUSTERED INDEX
は自動的にソートされます。
OrderDetailid
はOrderID
よりも選択的ですが、Orderid
は他の利点に加えて十分に選択的です。
そのため、OrderDetailテーブルのOrderedIDをクラスター化インデックスとして持つと、各注文の順序が保持されます(OrderDetailテーブルでは、各注文が順番に並べられます)。
はい。
このようにOrderDetailテーブルを配置すると、パフォーマンスが向上しますか? OrderDetailIDとは対照的に、OrderIDを中心としたクラスタリングの利点は何ですか?
ほとんどの重要なクエリは、OrderIDのみを使用してOrderDetailテーブルからレコードを取得します。ですよね?ほとんどのクエリは述語でOrderIDを使用するため、クラスター化インデックスにはOrderidが最適です。
ただし、注文は多くのパーツで構成されるため、各OrderIDには多くの行があります。
上記のインデックスの選択性について説明しようとしました。各Orderid
は最大でいくつの部分を持つことができますか?5、10、50?
最善の方法は、Real Table
数百万のレコードと1つの実際のクエリでテストします。real table
構造とそのdata type
。
答えは簡単です。はい!おそらくこれはアプリを変更することも意味します。
2番目のデザインははるかに優れています。 Order Date、Due Dateなどは繰り返さないでください。ただし、OrderDetailの主キーをIDに変更することを検討してください。さらに、Orderテーブルでは、IDも主キーとして配置します。もちろん、そのような列は外部キーとしてOrder Detailテーブルに存在する必要があります。注文のパーツIDが1つだけである必要があると思うのはなぜですか?あなたのビジネスがあなたを示唆しているなら、それは大丈夫です。しかし、IMO、すべてが起こる可能性があるため、これは将来的に制限になる可能性があります。