2013-04-18 11 views
5

私はこのような結論に達しました。以下のように、シーク/スキャンを行います。しかし、私は得られませんでした。 なぜ第1ケースでスキャンし、第2ケースでシークしますか?私は第3のケースを理解した。likeとwhereパターンの列のインデックス?

SELECT c.contactname FROM Sales.Customers c 
WHERE c.contactname LIKE '%a'-- Does a Scan 1st Case 

SELECT c.contactname FROM Sales.Customers c 
WHERE c.contactname LIKE 'a%'-- Does a Seek 2nd Case 

SELECT c.contactname FROM Sales.Customers c 
WHERE c.contactname LIKE '%a%'-- Does a Scan 

私はビルドが数字のために、それはより大きくより少ないと比較しますと はどのようにインデックスツリーの意志を横断行います場合は、私たちのような.. インデックスツリーになりますどのようにサンプルデータの下に持っている担当者名にインデックスを構築した場合以下の場合に横断する。

c.contactname 

mark 
anna 
krishna 
nadejda 
allen 
bob 
cab 

答えて

4

3番目のケースと同じ理由で、最初のケースでスキャンを行います。インデックスは、文字列の先頭からのデータに基づいて検索します。パターンの始めにワイルドカードを使用すると、索引をインテリジェントに検索する方法がありません。索引は文字列の字句比較(アルファベット順)比較を行います。これは比較より小さいか大きい比較です。

ツリーはこのようになります:インデックスはどこ各支店に行くかわからうとして

 /nadejda 
    mark 
/ \krishna 
cab 
    \ /bob 
    anna 
     \allen 

ので、a%を探しては、行うことができます。たとえば、C> A、左に移動します。 %aの検索は効率的ではありません。各ノードがAで終わったかどうかを知るためには、インデックスはすべてのデータを読み取る必要があります。インデックスを使用してすべてのデータを読み取ることはオーバーヘッドの無駄になります。

4

これは実際、SQL Serverが動作する方法です。あなたはなぜ尋ねています。

インデックスについて考えてみましょう。機能的には、contactnameをアルファベット順に格納していると考えることができます。これは、辞書や電話帳によく似ています。 (はい、通常はより複雑なデータ構造、通常はBツリーですが、結果は順番に項目です)。

contactname like 'a%'と言うと、クエリオプティマイザは、文字「a」で始まるエントリだけを調べる必要があることを認識しています。索引はそれらがどこにあるかを正確に知るので、オプティマイザはそれらに到達するためにシークを使用できます。 SQL Serverはこの最適化をlikeに実装しています(すべてのデータベースがこれを行うわけではありません)。

あなたがcontactname like '%a'と言うとき、あなたは "私には 'a'で終わるエントリを見つけます。それは辞書を見て "a"で終わるすべての単語を得るのが大好きです。注文には何の助けもありません。 "a"で始まり "a"で終わるエントリがあるかもしれません "z"で始まり "a"で終わるエントリがあるかもしれませんので、これらのタイプの式はシークではなくスキャンを必要とします

4
あなたは、文字列の列に索引を作成するときのためにこれを分解するので、[OK]を

。あなたのデータは、このように保存されているので、それが最初の文字でそれらを格納します。ですから、あなたのやっているとき

allen 
anna 
bob 
cab 
krishna 
mark 
nadejda 

LIKE 'a%' Sqlサーバーではインデックスを使用して、最初に 'A'が付いたすべての順序を調べることで結果を切り捨てることができますが、末尾にワイルドカードを置くと、エンジンは全体をスキャンするようになりましたt手紙Aで終わるものを探すことができます。

もちろんこれは信じられないほど簡単な説明です。

+1

*「初めに「A」ですべてのものを見ることによって」* ...''a ''で始まらない文字が見つかるとすぐに停止します(このサンプルでは' bob'など)。 –