2016-06-12 9 views
1

SQL実行計画、私は2つの類似のテーブルを持っている

CREATE TABLE [dbo].[StockPrices] (
    [Id]  INT    IDENTITY (1, 1) NOT NULL, 
    [CompanyId] INT    NOT NULL, 
    [Date]  DATETIME  NOT NULL, 
    [Open]  DECIMAL (18, 2) NOT NULL, 
    [Close]  DECIMAL (18, 2) NOT NULL, 
    [Low]  DECIMAL (18, 2) NOT NULL, 
    [High]  DECIMAL (18, 2) NOT NULL, 
    [Volume] INT    NOT NULL, 
    CONSTRAINT [PK_dbo.StockPrices] PRIMARY KEY NONCLUSTERED ([Id] ASC), 
    CONSTRAINT [FK_dbo.StockPrices_dbo.Companies_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Companies] ([Id]) ON DELETE CASCADE 
); 

GO 
CREATE CLUSTERED INDEX [IX_CompanyId] ON [dbo].[StockPrices]([CompanyId] ASC); 

GO 
CREATE NONCLUSTERED INDEX [IX_Date] ON [dbo].[StockPrices]([Date] ASC); 

CREATE TABLE [dbo].[News] (
    [Id]    INT   IDENTITY (1, 1) NOT NULL, 
    [NewsProviderId] INT   NOT NULL, 
    [CompanyId]  INT   NOT NULL, 
    [Date]   DATETIME  NOT NULL, 
    [Title]   NVARCHAR (128) NOT NULL, 
    [Description] NVARCHAR (256) NOT NULL, 
    [Url]   NVARCHAR (256) NOT NULL, 
    CONSTRAINT [PK_dbo.News] PRIMARY KEY NONCLUSTERED ([Id] ASC), 
    CONSTRAINT [FK_dbo.News_dbo.Companies_CompanyId] FOREIGN KEY ([CompanyId]) REFERENCES [dbo].[Companies] ([Id]) ON DELETE CASCADE 
); 
GO 

CREATE CLUSTERED INDEX [IX_CompanyId] ON [dbo].[News]([CompanyId] ASC); 
GO 

CREATE NONCLUSTERED INDEX [IX_Date] ON [dbo].[News]([Date] ASC); 
GO 

と2つの類似したクエリ

select * 
from news 
where companyid = 1 
    and date >= '01/01/2010' 
    and date <= '01/31/2010' 
order by date; 

select * 
from stockprices 
where companyid = 1 
    and date >= '01/01/2010' 
    and date <= '01/31/2010' 
order by date; 

と私は2つの完全に異なる実際の実行は

を計画して取得しています

Query1を:バッチに相対:86%

SELECT(COST 0%)< - ネストされたループ(Inneer参加)(コスト0%)< - インデックス(非クラスタ化)をシーク[ニュース] [IX_Date]。 (原価1%) < - キー検索(クラスタ)[ニュース] [IX_CompanyId](99%のコスト)

クエリ2:バッチに相対:14%

SELECT(Cost0の%)< - 分類(33%コスト)< - クラスタ化インデックススキャン(クラスタ)[StockPrices]は、私がなぜわからない

をIX_CompanyId?アドバイスできますか?

答えて

3

最初のものは、日付順にクラスタリングされていない索引でシークを使用し、companyid = 1に一致する行の残りの列を取得するためにキー参照を使用しています。

第2の方法は、カバリングインデックスでスキャンを行い、次にフィルタリングされた結果をソートすることです。

これは、一致すると見積もられるテーブルの割合と2つのインデックスの幅(some example calculations here)に応じたコストベースの決定です。

キールックアップは、関連するページと行を特定するためにクラスタ化インデックスシークを実行する必要があるため、高価です。つまり、ノンクラスタード・インデックス・シークによって検出された各行のの複数のページを読み取る必要があります(クラスタード・インデックスの深さと同じくらいのページ数)。さらに、1つの行で見つかったクラスタ化インデックスページは、次の行のページと相関がない可能性があり、ランダムなIOが多数発生します。

結果として、プランがインデックススキャンに切り替わる前のティッピングポイントは、テーブルの非常に低い割合になる可能性があります。この場合、非カバレッジインデックスがソートを避けることができるという事実は、他の点よりもティッピングポイントを少し高くする可能性があります。

それぞれの推定行を見てください。 Newsテーブルにはさまざまな文字列が含まれており、StockPricesテーブルの数値よりもクラスタ化インデックスページの行数が少なくて済む可能性があるため、Newsのフルクラスタードインデックススキャンの方が相対的に高価になり、

関連する問題