少し前に同僚と話をしましたが、彼はデータベースに保存されているすべての値を理解するのが難しいため、ビットマスクの使用に間違いなく反対しました。私の意見では、例えば現在のユーザーの役割を決定するためにそれらを使用することは必ずしも悪い考えではありません。それ以外の場合は、別のテーブルに保存する必要があり、これによりもう1つのJOINが発生します。私が間違っているかどうか教えてもらえますか?ビットマスクを使用する他の副作用、利点/欠点はありますか?
少し前に同僚と話をしましたが、彼はデータベースに保存されているすべての値を理解するのが難しいため、ビットマスクの使用に間違いなく反対しました。私の意見では、例えば現在のユーザーの役割を決定するためにそれらを使用することは必ずしも悪い考えではありません。それ以外の場合は、別のテーブルに保存する必要があり、これによりもう1つのJOINが発生します。私が間違っているかどうか教えてもらえますか?ビットマスクを使用する他の副作用、利点/欠点はありますか?
回答:
私は、ビットマスクを使用してユーザーロールの割り当てを保存するアプリケーションを使用しています。それはお尻の痛みです。もしこれが私を偏見させ、罪を犯したとしても。
リレーショナルデータベースを既に使用している場合、それはほとんどのリレーショナル理論とすべての正規化ルールに違反するアンチパターンです。独自のデータストレージを構築する場合、それほど悪い考えではないかもしれません。
結合されるテーブルが多すぎるなどの問題がありますが、これを処理するためにリレーショナルデータベースが構築されます。インデックス、インデックス付きビューなど、パフォーマンスが問題になる場合、多くの追加機能があります。検索する値がそれほど頻繁に変更されない場合でも、ビットマスクの利点は、インデックス作成を管理するオーバーヘッドがデータベース上で非常に簡単です。
データベースはデータの集計に優れていますが、データセットに複雑な数式やスカラー関数などを導入し始めると、データベースが遅くなる可能性があります。アプリでビット単位の操作を行うことはできますが、関連データを取得すること(ユーザーの役割を調べること)だけを行う場合、データストレージの最適な機能を活用することはできません。
それに対する私の最後の議論は、他の開発者にとってのシンプルさです。ユーザー、ロール、および割り当てがあります。多対多のリレーションセット(複数のリレーションがあるため)は非常に一般的であるため、管理が容易である必要があります。それはただのCRUDのものです。
where some_bit_mask & 12 > 0
、行ごとのスキャンなしでは行を検索できません。
user_role_map
またはuser_priv_map
テーブルで十分です。
あなたはすでに関連する長所と短所に名前を付けています:
何をすべきかを決定するには、さらに情報が必要です。
そのため、リスク要因を収集してから重みを付け、プロがデメリットを上回るかどうかを確認する必要があります。
あなたが本当に、本当に、本当にディスクスペースに縛られているなら、ユーザーパーミッションのためにビットマップを検討するかもしれません。パフォーマンスが心配な場合は、それらを完全に忘れてください。それらをバラバラにすると実際には遅くなります。ビットマップフィールドに意味のあるインデックスを作成することはできません。その結果、データベーステーブルスキャンが発生します。これは常にパフォーマンスを低下させます。
あなたがAmazonまたはNetflixでない限り、ユーザーの許可に関係するデータの量は、あなたが保持している他のすべてのものと比較して無視できます。
真面目なDBMSは、明滅することなく「余分な結合」を処理できます。
ストレージが高価だった頃、ビットマスクの利点は、スペースを節約できることでした。ビッグデータの時代、これはかつての問題ではありません。
あなたが引用する例を挙げると、ビットマスクとして保存されたロールは、最初の標準形式に違反するため、データベース設計の観点からはコード臭のようなものになります。この意味で、それらはアンチパターンです。
このすべてが言われている、それはどちらかである必要はありません。データをビットマスクとして保存し、その場でユーザーロールを取得できるビューを作成できます。また、どのユーザーが同じ役割を持っているかを一目で確認できるという利点もあります。
ビットマスクを使用する唯一の利点は、ビットフィールドの意味が静的でない場合です。リレーショナルテーブルは、各フィールドがレコード上にあるものを事前に知っている場合にのみ機能しますCREATE TABLE
。結局、DDLステートメントでフィールドを識別する必要があります。
場合は、各ビットフィールドの意味は、実行時に設定可能である、またはそれ以外の場合は事前に知られていない、それは可能性があるビットフィールドとしてブール値を格納するために意味をなします。それでも、それは任意のフィールドを持つテーブルを定義することが可能である:field_1
、field_2
まだ理想的ではないものの、などこれは、あなたのクリーナーリレーショナル設計を提供します。どちらのソリューションも理想的ではないため、これがビットフィールドよりも優先されるかどうかは、主に意見の問題です。
開発中にビットが何を表すかがわかっている場合は、ビットごとにフィールドを作成し、意味のある名前を付けます。
内側のプラットフォーム効果に注意してください。最終的に任意のフィールドを適切に定義する場合、それは1つのことですが、それよりも大きくなりすぎると、リレーショナルデータベース内でリレーショナルデータベースを再発明することになります。
私はビットマスクについてあいまいです。彼らの中傷者のほとんどは、バイナリと16進数を理解していないことがわかります。明確にするために、適切なニーモニックを使用します。
上記で言及されていない利点は、時間のかかる可能性のある新しい列の追加なしに、ビットマスクに新しい意味を追加できることです。私たちのdbデザイナー(私の前にいた)がテーブルにそれらを置いて、毎日500万件の新しいレコードを取得しています。新しい列を追加して新しい動作を表すには時間がかかりますが、新しいビット(64のうち33を消費しました)を定義するためにテーブルを再構築する必要はありません。
いいえ、ビットマスクにインデックスを付けることはできませんが、33個のインデックスを作成するのはばかげているため、クロールへの挿入が遅くなります。テーブル検索では、日付とレコードの「所有者」インデックスが使用されるため、可能であれば、このビットマスクのインデックスは使用されません。
目標がディスク領域を節約することだけである場合、それは悪い考えだと思います。
ただし、ビットフィールドの使用を正当化できる場合があります。