3

みなさん、こんにちは。

私はデータベースとデータベース設計について学んでいますが、まだ自分では答えられない質問に到達しています。ですから、私よりも知識や経験のある人が答えられることを期待して、コミュニティに質問を投げかけます。

私は、艦隊全体の在庫レベルを追跡するデータベースの作成を任されています。

現在の設計には、すべての可能な部品(機械の種類、部品番号、製造元、シリアル番号など)のリストが記載された各船の表があります。

これは、機械または部品の詳細を何度も(実際には船の数だけ)複製できることを意味します。

私は自分で学んだことに基づいて再設計を試みてきました。次のような方針で設計を提案します。

[SHIP]
ID, Name, Class, Tonnage, Fleet, Superintendent etc.

[Machinery]
ID, Type, Make, Model etc. (Can have separate table for manufacturers and types if required)

[Part]
ID, Part number, Description, etc.

上記は3つの主要なテーブルであり、現在は困難になり始めています。

各船は複数の機械アイテムを持つことができ、各機械アイテムは複数の船に存在する可能性があります(ジャンクションテーブルが必要です)

各機械アイテムは複数のパーツを持つことができ、各パーツは複数の機械アイテムに属することができます(別のジャンクションテーブル)

ジャンクションテーブルを巨大にする数十万のパーツが存在する可能性があります。

さらに、在庫を追跡したい場合は、別のジャンクションテーブルを見ています。

[Stock Level]
ShipID, PartID, Stock Level

また、最小在庫が必要な場合(在庫レベルと組み合わせることができますか?)

[Min Stock]
ShipID, PartID, Min Stock

そして最後に、正規化されたデータベース(つまり、Part No.1、Part No.2、またはSerial No.1、Serial No.2がない)を探している場合

いくつかの追加のテーブルが必要になります

[Serial Numbers]
ShipID, MachineryID, Serial No

[Part Numbers]
PartID, Part Number

シリアル番号はおそらくかなり標準的で問題ありませんが、[部品番号]には少なくとも[部品]テーブルと同じ数のレコードが必要です。

マップ(画像なしで表現できる限り、簡単にするためにジャンクションは省略されています)

  <>V represent many 
  -| represent one

   -----< Serial Numbers
  |             V
  |             |
Ship >---< Machinery >---< Parts ---< Part Numbers
  V                          V
  |                          |
   ------ Stock Level -------

さて、本当の問題は、このような巨大なジャンクションテーブルを排除する基本的な設計原則に何かが欠けているのか、それともこの種のデータベースで予想されることなのかということです。

また、正規化で元のテーブルの追加の列ではなく、少なくとも同じ数のレコードを持つ追加のテーブルが必要な部品番号の場合、これは後でクエリ速度を向上させるために非正規化するようなものですか?

外部リソース(他のフォーラム、チュートリアル、書籍を含む)へのヒント、ヒント、またはポインターをいただければ幸いです。

すべての回答を歓迎します。ご協力いただきありがとうございます。

デイブ

4

2 に答える 2

7

まず、いいえ:多対多の関係は悪い設計の指標ではありません。

次に、結合テーブルは、接続しているテーブルよりも常に大きくなります。それぞれ100レコードのテーブルが2つある場合、結合テーブルは最大10000レコードになる可能性があります。

ただし、結合テーブルは整数のペアにすぎず、インデックスを作成すると非常に高速になります。

追加するために編集:

あなたはコメントしました:

インデックス作成はDBMSによって行われたと思います

何にインデックスを付けるかをDBMSに指示するのはあなた次第です。その後、インデックスを最新の状態に保つことが自動的に行われます。

一部のDBMSには、動作中のシステムを監視し、どのインデックスが有益であるかをアドバイスするツールがあります。

あなたの設計プロセスは良いので、おそらく正しい方向に進んでいます。

于 2012-07-24T14:55:05.030 に答える
2

egruninが言ったことに加えて、DBMSがそれをサポートしている場合、ジャンクションテーブルはクラスタリング(別名インデックス編成テーブル)の良い候補になることがよくあります。

たとえば、クラスタリング...

[Stock Level]
ShipID, PartID, Stock Level

...同じ物理的に近い行を格納ShipIDするため、特定の船に関連付けられているすべての行を取得するのが非常に効率的になります。

一方、クラスタリング...

[Stock Level]
PartID, ShipID, Stock Level

...同じPartID近くにある行を格納するため、特定の部分に関連付けられた行を効率的に取得できます。

これらの両方の方向でクエリを実行する必要がある場合は、2つのインデックス({ShipID, PartID}および{PartID, ShipID})が必要です。通常、クラスター化テーブルのセカンダリインデックスには、PK全体のコピーが含まれている必要があり、追加のストレージが必要であり、ダブルルックアップが発生するため、複数のインデックスを持つテーブルのクラスター化にはコストがかかります。ただし、この場合は、とにかく同じフィールドを(異なる順序で)カバーするため、セカンダリインデックスにオーバーヘッドはありません。ダブルルックアップを回避するために、セカンダリインデックスでカバー することを検討することもできます(クラスタリングインデックスはすでに自然にカバーしています)。Stock Level

DBMSがクラスタリングをサポートしていない場合は、インデックス作成{ShipID, PartID, Stock Level}(または{PartID, ShipID, Stock Level}その両方)を検討してください。このように、クエリはインデックスでカバーされ、テーブルヒープにアクセスする必要はありません。基本的に、(冗長な)テーブルヒープで追加のスペースが無駄になることを除いて、クラスタリングの効果を実現します。


それに加えて、一部のDBMSは最先端のインデックス圧縮をサポートしており、ジャンクションテーブルのインデックスで繰り返される値のストレージスペースを大幅に削減します。最大限の効果を得るには、クラスター化されたテーブル(それ自体がインデックスです)を圧縮します。

于 2012-07-24T19:49:14.920 に答える