1. ホーム
  2. c#

フラグを連想表ではなく、ビットマスクとして格納する方が良いのはどのような場合ですか?

2023-09-25 12:17:12

質問

私は、ユーザーがさまざまな機能 (例: 読み取り、作成、ダウンロード、印刷、承認など) を使用するための異なる権限を持っているアプリケーションに取り組んでいます。権限の一覧は頻繁に変更されることはないと思われます。これらの権限をデータベースに格納する方法について、いくつかのオプションがあります。

どのような場合にオプション 2 が良いのでしょうか?

オプション1

連想表を使用する。

ユーザー
----
UserId (PK)
名前
部署名

アクセス許可
----
パーミッションID (PK)
名前
ユーザパーミッション
----
ユーザID (FK)
パーミッションID (FK)

オプション2

各ユーザーのビットマスクを保存する。

ユーザ
----
UserId (PK)
名前
部署名
アクセス権
[Flags]
enum Permissions {
    Read = 1,
    Create = 2,
    Download = 4,
    Print = 8,
    Approve = 16
}

どのように解決するのですか?

すばらしい質問ですね。

まず、quot;better"について、いくつかの仮定を立ててみましょう。

ディスク容量についてはあまり気にしないと仮定します。ビットマスクは容量の点から見て効率的ですが、SQL サーバーを使用している場合、それはあまり重要ではないと思われます。

私は、あなたが速度を気にしていると仮定しています。ビットマスクは、計算を使用する場合は非常に高速になりますが、ビットマスクをクエリする場合はインデックスを使用することはできません。これはそれほど重要ではありませんが、どのユーザーが作成アクセス権を持っているかを知りたい場合、クエリーは次のようになります。

select * from user where permsission & CREATE = TRUE

(今日は出先で SQL Server にアクセスできません)。そのクエリは、数学的な操作のため、インデックスを使用することができません。

保守性を気にされているようですが。保守性の観点から、ビットマスクは、明示的なパーミッションの格納と同様に、根本的な問題領域として表現力がありません。ほぼ間違いなく、データベースを含む複数のコンポーネントでビットマスク フラグの値を同期させる必要があります。不可能ではありませんが、背中の痛みになります。

したがって、"より良い" を評価する別の方法がない限り、ビットマスクのルートは、正規化されたデータベース構造でパーミッションを格納するのと同じくらい良くないと言えるでしょう。完全に機能不全のデータベースでない限り、これを測定することはできません (アクティブなインデックスの利点がないクエリは、数千レコードでも顕著に遅くなることがあります)。