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


15

テーブルの各レコードにビット配列を保存し、次の操作をサポートする必要があります。

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

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

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

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

これまで見てきたことから、私のオプションは次のとおりです。

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

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

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

回答:


12

これに単一のフィールドを使用しないほど強く主張することはできません

現在、bigintビットマスクフィールドを持つ非常に大きなデータセットの維持を扱っていますが、これはパフォーマンスの悪夢です。

1ビットだけチェックすれば大丈夫です。複数のビットをチェックすると、パフォーマンスが急速に低下します。

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

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

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

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

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


1
回避策についてもう少し詳しく説明していただけますか?私は同じ基本的な問題に対処しようとしているが、それをどうするのが最善かわからないため、これを見つけました。
ジョシュアフランク

4

保存する必要があるのが中程度の数のtrue / false値だけである場合、bitデータ型を使用できます。

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.