2016-06-21 13 views
0

以下のSELECTステートメント(下記)はインデックスシークを使用していませんが、インデックススキャンはなぜですか?行の数が少なすぎるか、何か不足していますか?オプティマイザがインデックスを使用しないのはなぜですか?

テストデータ:

-- Init Tables 

IF OBJECT_ID ('tempdb..#wat') IS NOT NULL 
DROP TABLE #wat; 

IF OBJECT_ID ('tempdb..#jam') IS NOT NULL 
DROP TABLE #jam; 

CREATE TABLE #wat (
ID INT IDENTITY(1,1) NOT NULL, 
Name VARCHAR(15) NOT NULL, 
Den DATETIME NOT NULL 
) 

CREATE TABLE #jam (
ID INT IDENTITY(1,1) NOT NULL, 
Name VARCHAR(15) NOT NULL 
) 

-- Populate Temp Tables with Random Data 

DECLARE @length INT 
     ,@charpool VARCHAR(255) 
     ,@poolLength INT 
     ,@RandomString VARCHAR(255) 
     ,@LoopCount INT 

SET @Length = RAND() * 5 + 8 
SET @CharPool = 'abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789' 
SET @PoolLength = LEN(@CharPool) 
SET @LoopCount = 0 
SET @RandomString = '' 

WHILE (@LoopCount < 500) 
BEGIN 

    INSERT INTO #jam (Name) 
    SELECT SUBSTRING(@Charpool, CONVERT(int, RAND() * @PoolLength), 5) 
    SET @LoopCount = @LoopCount + 1 

END 

-- Insert Rows into Second Temp Table 
INSERT INTO #wat(Name, Den) 
SELECT TOP 50 Name, GETDATE() 
FROM #jam 

-- Create Indexes 

--DROP INDEX IX_jedna ON #jam 
--DROP INDEX IX_dva ON #wat 
CREATE INDEX IX_jedna ON #jam (Name) INCLUDE (ID); 
CREATE INDEX IX_dva ON #wat (Name) INCLUDE (ID, Den); 

-- Select 

SELECT * 
FROM #jam j 
JOIN #wat w 
ON w.Name = j.Name 

実行計画:nested loops, hash match or merge join(あなたのケース)と別であってもよい:

enter image description here

+2

あなたに与えます。あなたのデータが小さいので、スキャンがうまくいく可能性があります。しかし、統計値が古くなったり、インデックスが失われたりする可能性があります。 –

+0

私はあなたのコードを実行し、インデックスを取得しました。シーク時の推定行数は12でした。コードを繰り返し実行し、推定された行数が10〜15で毎回検索しました。 –

+0

実行しているSQL Serverのバージョンは何ですか? –

答えて

0

は、オプティマイザはジョンを行うためのいくつかの方法があります。 あなたのデータに依存しています:行数、存在しているインデックスと統計idはどちらが良いかを決定します。

あなたの例のオプティマイザでは、多対多の関係があるとみなします。そして、このフィールドによって両方のテーブルが索引付けされています。

なぜマージ結合? - 論理的に - 両方のテーブルを並行して移動します。そして、サーバーはそれを一度だけ行う必要があります。

あなたが望むようにseekを作成するには、サーバは最初のテーブルを一度移動しなければならず、すべてのレコードが別のテーブルに一致するので、2番目のテーブルでシークする必要があります。彼が探している場合、サーバーはすべてのレコードを読み取ります。また、シークを使用すると利益は得られません(1000シークは、1000レコードを通して1つの単純なループよりもさらに多くのシークを探します)。

seek一致する一致のないレコードとクエリのwhere句を追加します。

UPD

もシンプル

where j.ID = 1 

追加するには、このデータのヒストグラムを見て、最速になるだろうかを決めるために起こってseek

関連する問題