2017-09-13 12 views
2

私は後で私を悩ませているSQL Serverのインデックスについてこの質問があります。ノンクラスタード・インデックスでは、2番目、3番目、4番目...の列はどのようにソートされますか?

CREATE NONCLUSTERED INDEX IX_LastName ON TelephoneBook (
    LastName, 
    FirstName, 
    PhoneNumber 
) 

と、このテーブルは、行の数十万人を持っていることを想像:このようなインデックスを持つ

CREATE TABLE TelephoneBook (
    FirstName nvarchar(50), 
    LastName nvarchar(50), 
    PhoneNumber nvarchar(50) 
) 

は、このようなテーブルを想像してみてください。

私は、姓がBで始まり、ファーストネームが「John」であるすべての人を選択したいとしましょう。インデックスは、我々はとにかくBで始まるLastNamesのすべてのそれためのグループをスキャンする必要がある行の数を減らすのを助けることができるので、それはまたのためにこれを行うん、

SELECT 
    * 
FROM TelephoneBook 
WHERE LastName like 'B%' 
AND FirstName='John' 

:私は、次のクエリを記述しますファーストネーム?または、データベースは、Bで始まるすべての行を検索して、最初の名前が「John」のものを検索しますか?

つまり、2番目、3番目、4番目、...の列はどのようにインデックスにソートされていますか?この場合もアルファベット順ですか?Johannaを見つけるのは簡単ですか?あるいは、彼らはある種のランダムな順序であったり、別の順序で存在したりしていますか?

EDIT:私は上記のSELECTステートメントでこれを読んだだけなので、インデックスは姓がBで始まるレコードへの検索の絞り込みにのみ使用されますが、インデックスはすべての行をJohannaで検索するために使用することはできません(また、すべての 'B'行をスキャンすることになります)。それがなぜあるのだろうか?私は何を得ていないのですか?

答えて

2

便利な省略形として、where節にインデックスのキーが最初の不等式まで使用されています。ワイルドカード付きのlikeは不等式とみなされます。

インデックスは、最初の値を検索するためにのみ使用されます。ただし、エントリは最初の名前と一致するようにスキャンされるため、引き続きインデックスの使用方法が得られます。

もちろん、フルテーブルスキャンが適切であると判断した場合、オプティマイザはインデックスをまったく使用しないことにします。

+0

小さなテーブルのフルテーブルスキャンは、同じテーブルのクラスタ化されていないインデックスのルックアップよりも安価です。全テーブルのスキャンが悪いので、25行のテーブルでインデックスを強制的に使用する人がいました。クールな答え – Namphibian

1

この例では、指定されたクエリでゴードンの答えは正しいです。一般的には、列の値に基づいてバケットでレコードをグループ化するのではなく、インデックスのキー列に従って並べ替えることが重要であることに注意してください。つまり、このインデックスのレコードはLastNameに従って並べ替えられ、同じLastName値を共有するレコードの場合、FirstName値とPhoneNumber値の順にさらに並べ替えられます。このインデックスの列の並べ替え順序は指定されていませんが、SQL Server defaults unspecified sort orders to ASC(ending)であるため、これらの列は実際に索引でレキシカルにソートされています。

特定のケースでは、クエリオプティマイザは、最初の列のインデックスを調べて、Gordonの回答のようにレコードを決定することにしましたが、オプティマイザがそれが良いと判断した場合、照会自体と照会しているレコードの統計に応じて、索引の列を使用するか、まったく使用しないことがあります。

0

論理的に言えば、インデックスはキーの順にキー値によってソートされます。この場合、LastName(テキストとしてソート)、FirstName(テキストとしてソート)、PhoneNumber(テキストとしてソート)...インクルードされた列はまったくソートされません。

あなたのケースでは、後続のワイルドカードがまだSARGableであることがわかっているので、そのデータプールから「B」で始まるすべてのデータに絞って検索することを期待しています。 FirstName = 'John'を持つ行だけを含むようにさらにフィルタリングされます。あなたはそれをインデックスシークとそれに続くレンジシークと考えることができます。

関連する問題