web-dev-qa-db-ja.com

フラグの配列(ビットマップ/ビット配列)を格納するためのデータ型

テーブルのレコードごとにビット配列を格納して、次の操作をサポートする必要があります。

  • ビットが設定されているかどうかのテスト、およびビットの設定(SQLを使用)

  • ADO 2.8(ADO.NETではない)を使用した値のクエリと設定

  • インデックス作成(「カバーインデックス」機能を利用するため)

この配列に格納されるビットの最大数は固定ですただし32を超える場合があります。つまり、単純なint列が常に機能するとは限りません。

これまでに見てきたことから、私の選択肢は次のとおりです。

  1. 複数のint列を使用する
  2. bigintを使用します(ビット数が64以下である限り機能します)
  3. binaryを使用します

最初のオプションは機能しますが、データにアクセスするコードでかなりのリファクタリングが必要です。 2番目のオプションは一時的な救済のみです。これまでの検索では、ADOがbigintbinaryの経験がなく、他のオプションについては知りません。

要件を考慮して、どのデータ型を選択しますか?

15
krlmlr

私は十分に強く主張することはできませんこれに単一のフィールドを使用しないでください。

私は現在、bigintビットマスクフィールドを含む非常に大きなデータセットを維持することに取り組んでおり、それはパフォーマンスの悪夢のようなものです。

シングルビットをチェックする場合は問題ありません。複数のビットをチェックすると、パフォーマンスがすぐに低下します。

ビットマスク整数の性質により、データ分布は非常に不均衡になり、最適ではない計画が得られます。

複数のビットチェックにより、すべての行に対して実行される関数を使用した範囲スキャンまたはインデックススキャンが行われます。それは混乱です。

私の回避策は簡単でした。チェックする各条件のPKを格納するテーブルを作成しました。これは最初は直観に反しますが、必要なスペースは少なく(PKのみを格納します)、特にUNIQUE CLUSTERED INDEXを使用する場合、検索は高速です。

メインテーブルに影響を与えることなく、必要な数の条件を追加できます。また、更新はメインテーブルに影響しません。

すべてのルックアップテーブルに個別にインデックスを付けるだけであり、クラスター化されたキーがメインテーブルで同じであり、ルックアップすべての評価がmerge joinsであるため、インデックス作成は簡単であり、非常に効率的です。

12
JNK

保存する必要があるのが適切な数のtrue/false値である場合は、bitデータ型を使用できます。

内部的に、SQL Serverはbit列をバイトの「チャンク」にパックして格納します。したがって、テーブルの最大8つのbit列について、SQLはそれをパックされた1バイトとして格納します。 2-16バイトの9-16 bit列など。

列の制限に近づくように聞こえないので、これは非常に簡単です。そしてもちろん、それらをそのようにうまく分離しておくことで、読みやすいように列に名前を付け、通常どおりにすべてのインデックス作成の可能性を得ることができます(フラグが非常に選択的である場合、フィルターされたインデックスは2008+を対象とすることができる場合に役立ちます)。

自分でビットパッキングを行うと、インデックス付け(おそらく、マスクの各位置を表すために計算およびインデックス付けされたbit列)を実行するのがはるかに複雑になります...しかし、bit直接)。

4
Jon Seigel