web-dev-qa-db-ja.com

データベース行のフラグ、ベストプラクティス

好奇心からこれをお願いしています。基本的に私の質問は、フラグのように機能するものを持つために行エントリが必要なデータベースがある場合、ベストプラクティスは何ですか?これの良い例は、スタックオーバーフローのバッジ、またはBugzillaのオペレーティングシステムフィールドです。フラグのサブセットは、特定のエントリに設定できます。

通常、私はcとc ++の作業を行うので、私の直感的な反応は、符号なし整数フィールドを反転できるビットのセットとして使用することです。最も明白なのは拡張性です。私が持つことができるフラグの数には厳しい上限があります。

他のいくつかのソリューションも考えられます。これらのソリューションは拡張性は高くなりますが、すべての情報を取得するには複数の選択が必要になるため、パフォーマンスの問題が発生します。

それで、これを行う「正しい」方法は何ですか?

35
Evan Teran

閉じたフラグのセット(stackoverflowバッジなど)から無制限の選択が本当に必要な場合、「リレーショナルな方法」は、フラグのテーブルと、それらのフラグをターゲットエンティティに関連付ける別のテーブルを作成することです。したがって、users、flags、usersToFlags。

ただし、スペース効率が重大な問題でクエリ能力が問題でない場合は、符号なしマスクもほぼ同様に機能します。

27
Daniel Spiewak

一般的に言って、ビットマスクフィールドは避けます。それらは将来読むのが難しく、理解するにはデータについてより深い知識が必要です。

リレーショナルソリューションは以前に提案されています。あなたが概説した例を考えると、私はこのようなものを(SQL Serverで)作成します:


CREATE TABLE Users (
  UserId INT IDENTITY(1, 1) PRIMARY KEY,
  FirstName VARCHAR(50),
  LastName VARCHAR(50),
  EmailAddress VARCHAR(255)
);

CREATE TABLE Badges (
  BadgeId INT IDENTITY(1, 1) PRIMARY KEY,
  [Name] VARCHAR(50),
  [Description] VARCHAR(255)
);

CREATE TABLE UserBadges (
  UserId INT REFERENCES Users(UserId),
  BadgeId INT REFERENCES Badges(BadgeId)
);
29

多くの場合、データベースのバックエンドなど、多くのことに依存しています。たとえば、MySQLを使用している場合、 SET datatype がまさに必要なものです。

基本的に、それはビットマスクであり、各ビットに値が割り当てられています。 MySQLは最大64ビットの値をサポートします(64の異なるトグルを意味します)。 8つしか必要ない場合は、行ごとに1バイトしか必要ありません。これはかなりの節約になります。

1つのフィールドに正直に64を超える値がある場合、フィールドはより複雑になる可能性があります。次に、MySQLが本質的に理解していない生のビットのセットであるBLOBデータ型に拡張することができます。これを使用して、MySQLが2進数、16進数、または10進数の値として扱いたい任意の数のビットフィールドを作成できますが、必要です。 64を超えるオプションが必要な場合は、アプリケーションに適した数のフィールドを作成します。欠点は、フィールドを人間が読めるようにすることが難しいことです。 BITデータ型 も64に制限されています。

5
Dan Udey

非常にリレーショナルなアプローチ

セットタイプのないデータベースの場合、新しいテーブルを開いて、各フラグが設定されているエンティティのセットを表すことができます。

例えば。テーブル「Students」の場合、「RegisteredStudents」、「SickStudents」、TroublesomeStudentsなどのテーブルを作成できます。各テーブルには、student_idという1つの列しかありません。どの学生が「登録済み」または「病気」であるかを知りたい場合、これは実際には非常に高速で、すべてのDBMSで同じように機能します。

4
Seun Osewa

データベースでこれがサポートされている場合は、BOOLEANデータ型を使用することをお勧めします。

それ以外の場合、最善の方法は、NUMBER(1)または同等のものを使用し、有効な値を(0,1)に制限する列にチェック制約を設定し、必要に応じてNULLにすることです。組み込み型がない場合は、文字列を使用するよりも、数値を使用するほうが曖昧さが少なくなります。 (trueの値は何ですか? "T"または "Y"または "t")

これの良い点は、SUM()を使用してTRUE行の数をカウントできることです。

SELECT COUNT(1), SUM(ActiveFlag)
FROM myusers;
3
WW.

フラグの意味が大きく異なり、SQLクエリまたはVIEWSで直接使用される場合、タイプの複数の列を使用する BOOLEAN 良いアイデアかもしれません。

いずれにしても、それらを個別に読み取り、変更するため、各フラグを追加の列に入力します。フラグをグループ化する場合は、列名に共通のプレフィックスを付けます。つまり、次の代わりに:

CREATE TABLE ... (
    warnings INTEGER,
    errors   INTEGER,
    ...
)

あなたは使うべきです:

CREATE TABLE ... (
    warning_foo BOOLEAN,
    warning_bar BOOLEAN,
    warning_...
    error_foo   BOOLEAN,
    error_bar   BOOLEAN,
    error_...   BOOLEAN,
    ...
)

MySQLにはブール型はありませんが、そのために準標準のTINYINT(1)を使用して、0または1にのみ設定できます。

3
vog

フラグが少ししかない場合、または将来的にそうなる可能性がある場合は、フラグの個別のテーブルとそれらの間の多対多のテーブルを使用します。

いくつかのフラグがあり、それらをWHEREで使用する予定がない場合は、SET()またはビットフィールドなどを使用します。読みやすく、コンパクトですが、クエリが面倒で、ORMで頭痛の種になることもあります。

フラグが少ししかない場合goingがフラグになる場合---いくつかのBIT/BOOLEAN/etc列を作成します。

1
Eevee