RDBMS での適切な正規化は、テーブルの急増を意味します。整数フィールドは、直交データをビットとして格納できます。これは、リレーショナルの整合性を犠牲にすることなく、追加のテーブルの代わりとして使用できますか?
3 に答える
「多」に少数の既知の値がある 1 対多のリレーションシップの場合、リレーションシップは親テーブルに整数としてビットマスクとして格納でき、追加のテーブルの必要性を置き換えることができます。
テーブル Person があり、その人が訪れた大陸の数を知りたいとします。各大陸に「直交」ビット値を割り当てることから始めます。C# では、これには列挙型が適しています。
[Flags]
public enum JobAdvertisingRegion
{
NorthAmerica = 1, // or 1 << 0
SouthAmerica = 2, // 1 << 1
Europe = 4, // 1 << 2
Asia = 8, // 1 << 3
Africa = = 16, // 1 << 4
Australia = 32, // 1 << 5
Anarctica = 64 // 1 << 6
}
次に、Persons テーブルに、Contintents という int 列を単純に含めることができます。個人がヨーロッパとアジアを訪問したことを示すには:
UPDATE Persons SET Continents = (4 + 8) WHERE Id = whatever
南極を訪れた人物を検索するには、ビットごとの計算を使用します。
SELECT * FROM Persons WHERE Continents & 64 = 64
アフリカとアジアの両方を訪れた人物を検索するには:
SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8)
オーストラリアまたは南アメリカを訪れたことのある人を検索するには:
SELECT * FROM Persons WHERE Continents & (32 + 2) != 0
欠点の 1 つは、SQL では整数列にインデックスを付けることができますが、ビット コンポーネントにはインデックスを付けられないことです。上記のクエリについて、これを回避するためのいくつかの最適化:
SELECT * FROM Persons WHERE Continents & 64 = 64 AND Continents >= 64
SELECT * FROM Persons WHERE Continents & (16 + 8) = (16 + 8) AND Continents >= (16 + 8)
SELECT * FROM Persons WHERE Continents & (32 + 2) != 0 AND Continents >= 2
あなたの質問に対する答えは「いいえ」です。ビット フィールドは、対応するテーブルを持たないエンティティがデータベースにあるという単純な理由で、リレーショナルの整合性を犠牲にします。
とはいえ、多くのデータベースは、一般に「ビット」データ型を通じて、これをサポートしています。Mysql は、"set" データ型により、さらに強力なサポートを提供します。
主な問題は、セット内の要素について何も知らないことです。つまり、完全な名前は何か、いつデータベースに追加されたのかなどです。(列挙型は命名の問題の一部を回避します。) さらに、セットのサイズは制限されています。物事が制限されている例があるかもしれません。ただし、Matt の例はむしろここでの問題を強調しています。訪問した大陸のリストを表示できます。ただし、訪問した国に切り替えると、アプローチは必然的にまったく異なります。これは、国の数が単一の「単語」に収まらないためです。この点で、システムが大陸を国とはまったく異なる方法で処理することを望んでいますか? コンピューター ワードの 32 ビットまたは 64 ビットの制限によって設計上の決定を制限したいですか?
最後に、あなたはテーブルの急増を問題と見なしているようです。テーブルの急増は実際には解決策です。エンティティに関するすべてのデータは、システム全体に分散されるのではなく、テーブルに格納されます。インスタンスがいつ作成されたか、時間の経過とともにどのように変化したかなど、エンティティのインスタンスに関する情報を維持できます。「大陸」のエンティティは、誰かが大陸を必要とする場合に使用される可能性があります。
2 人の異なる開発者が大陸用に独自のビット マスクを開発することを決定したシステムで何が起こるか考えてみてください。適切に設計されたリレーショナル データベース (テーブル定義で外部キー リレーションシップが明示的に宣言されていることを意味します) では、このような混乱は発生しません。
さて、私はここで(現在の)世論に反して、いくつかの事実を単純に述べることにします.
- SQL とリレーショナル モデルは同じものではありません。
- リレーショナル モデル (理論) は、relvarsと呼ばれるリレーショナル変数で動作します。
- SQL データベースはテーブルを使用します。
- テーブルと relvar は同じではありませんが、すべての実用的な目的で同じである可能性があります。
- リレーショナル モデリング理論を使用するには、テーブルは relvar を表す必要があります。
テーブルがリレーショナル変数を表すには、次の条件が満たされている必要があります。
- 行に順序がない
- 列に順序がない
- 重複行なし
- すべての列と行の交点には、列定義型の値が 1 つだけあります
- 特別な非表示の列はありません (行 ID、オブジェクト ID ...)
したがって、リレーショナル設計理論の範囲外のテーブルと SQL を使用して多くのことを行うことができますが、「リレーショナル」の利点は失われます...
技術的には、あなたの投稿 (質問) には 2 つの答えがあります。
- はい、投稿のタイトルに。
- いいえ、投稿の本文に。