ビット列にインデックスを追加すると、挿入が大幅に遅くなりますか?


11

約100万から500万レコードのテーブルがあります。そのレコードのごく一部では、ビット列の1つが「TRUE」に設定されています。そのレコードをすばやく見つける必要があります。インデックスはこの列の検索を高速化できると思いますが、INSERTを恐れています。したがって、私の質問です。

データベースは一種のデータウェアハウスのように機能するため、多くのSELECTがあり、小さい(1日あたり最大10〜20)が、非常に大きいINSERT(一度に最大20万レコード)があります。データベースへのインポートの時間が長くなるのではないかと心配です。


5
SQL Serverのバージョンは何ですか?フィルターされたインデックスのように2008+に聞こえる場合は、必要なものである可能性があります。
マーティン・スミス

SQL Server 2005
marioosh 2014

1
テーブルを分割することができます(1列のみの新しいテーブル、テーブルのPKを追加します。これには、ビット列がtrueである行のみが入力されます-最後にビット列を削除することもできます)。ビューは、部分的なインデックスがないため、2005年にも機能します。
ypercubeᵀᴹ

インデックス付きビューには十分注意してください。1日あたり10〜20個の大きな挿入があるとおっしゃいましたが、インデックス付きビューのメンテナンスはパフォーマンス向上のメリットを超える可能性があります。状況を改善するために利用できるSQL 2005の「すぐに使える機能」はないと思います。ただし、現在のテーブル構造と既存のインデックスを一覧表示すると、別のデザインが見つかることがあります。
Anup Shah

回答:


8

100万レコードのビットのインデックスは役に立ちません。オプティマイザがこれを使用することは決してなく、維持するために支払うだけです。より良い代替策は、このビットをクラスター化インデックスの左端のキーとして追加することです。

しかし、私は暗闇の中でブラインドショットを行い、あなたが持っているものがキューパターンであると推測します。レコードは、ビットが「TRUE」に設定されたテーブルにドロップされ(つまり、「needsprocessing = true」)、バックグラウンドプロセスが見えるこれらのレコードについては、いくつかの処理を行い、ビットをFALSEに更新します。これは遍在するパターンであり、「パフォーマンス災害レシピパターン」としても愛情を込めて知られています。レコードをテーブルにドロップし、通知(新しく挿入されたレコードIDと同じくらい簡単な場合もあります)を同時にキューにドロップすることをお勧めしますテーブルをキューとして使用するを参照してください。


1
カーディナリティの高いユーザーが使用している可能性のある他のフィルター列がわからないため、ビット列を左端に配置しても意味がありません。これまでのところ、クラスター化インデックスの最後の選択肢はBIT列です。しかし、はい、「キューとしてのテーブルの使用」の優れたリファレンスとして+1。
Anup Shah

2
実際、私はテストを実行しました、そしてはい、それはインデックスを使用します。テーブル(Idアイデンティティ、myBitビット)を作成し、ビットが0の場合は100行、ビットが1の場合は2000000を追加します。統計が更新されていることを確認し(必要な場合)、myBit = 0でクエリを実行すると、インデックスが使用されます。
ケネスフィッシャー

@KennethFisher。ただし、挿入の一般的な高速パターンではTRUE / FALSEに更新されるとすぐに、統計は常に古くなります。明確なデザインを行うのではなく、オプティマイザーでロシアンルーレットをプレイしたい場合は、
当然の結果

「今までそれを使用することはありません」という文は、例99%のために保持しているが、我々はOPがであるものの場合知らない。私は成功したビットにインデックスされています。ユースケースが存在します。
usr

質問- ここでの答え間違っています、特に>「ビットフィールド(またはいくつかの狭い範囲)にインデックスを付ける場合、その値に一致する行の数だけワーキングセットを減らします。一致する行の数が少ない場合ワーキングセットが大幅に削減されます。50/ 50の分布を持つ多数の行の場合、インデックスを最新の状態に保つことと比較して、パフォーマンスの向上はほとんどありません。」どの場合、レコードの1%に一致するビットのインデックスは、大幅なブーストのために100万の99%をスキャンする必要をなくしますか?
drzaus

2

@MartinSmithが言ったように、SQL 2008にアップグレードする場合は、フィルターされたインデックスが最適なソリューションになります。ただし、平均的には、一般的なケースとして、インデックスを追加するとロード時間が長くなります。小さなインデックスは大きなインデックスよりも少ないです。

私が検討することの1つは、変更可能な既存のインデックスがあるかどうかです。既存のクエリが特定のインデックスを使用している場合、ビットカラムをそのインデックスの最後に追加しても、挿入への影響は最小限に抑えられ、クエリに見られるプラスの効果が得られます。

次に確認することは、「すでに多くのインデックスを持っていますか?」です。「たくさん」が何であるかについての明確で速い規則はありませんが、私が本当に新しいものを本当に必要としない限り、私は通常、10インデックスの規則で行くという制限があります。

最後に、テストインスタンスでテストします。数百万行のテーブルをセットアップし、その上でロードを実行し、インデックスを追加してから、再度ロードを実行して、ロード時間が大幅に増加するかどうかを確認します。

「有意義」が何であるかを本当に決定できるのはあなただけです。読み込み時間に5分を追加することが「重要」なマシンと、数時間の増加を安全に確認できるマシンがあります。

編集:

別のオプションは、テーブルを分割することです。Enterpriseエディションを使用していない場合でも、パーティションビューを使用する必要がある場合がありますが、それでも問題は解決します。あるパーティションにビット0を入れ、別のパーティションにビット1を入れます。どちらか一方のバージョンのみを挿入すると仮定すると、挿入を高速化することもできます。

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