2017-03-05 131 views
1

我有2个表SQL Server的执行计划问题

CREATE TABLE [dbo].[T2] (
    [Id] INT   IDENTITY (1, 1) NOT NULL, 
    [F1] NVARCHAR (100) NULL, 
    [F2] NVARCHAR (100) NULL, 
    [F3] NVARCHAR (MAX) NULL, 
    PRIMARY KEY CLUSTERED ([Id] ASC) 
); 

GO 
CREATE NONCLUSTERED INDEX [IX_T2_F1_F2] 
    ON [dbo].[T2]([F1] ASC, [F2] ASC); 

CREATE TABLE [dbo].[T3] (
    [Id] INT   IDENTITY (1, 1) NOT NULL, 
    [F1] NVARCHAR (100) NULL, 
    [F2] NVARCHAR (100) NULL, 
    [F3] NVARCHAR (MAX) NULL, 
    PRIMARY KEY CLUSTERED ([Id] ASC) 
); 

GO 
CREATE NONCLUSTERED INDEX [IX_T3_F1_F2] 
    ON [dbo].[T3]([F1] ASC, [F2] ASC) 
    INCLUDE([F3]); 

这些都是我的执行计划

enter image description here

的问题是,为什么查询# 2的执行计划不是Index Seek (NonClustered),为什么查询优化器选择扫描c关于PK的索引,而不是非聚集索引{F1,F2}

更新#1:

Query #2 Stats

+0

你可能在这些表中有0行,所以没关系。在那里放置一百万行并更新你的统计数据。 –

+0

@ ta.speot.is我在这两个表中都有100k行 – dizar47

+0

那么执行计划中的那些箭头非常窄 - SQL Server估计有多少行? –

回答

2

SELECT [F1],[F2],[F3] FROM [T2] WHERE ...需要三列,IX_T2_F1_F2只包含其中两个。

当涉及到覆盖索引的时候,SQL Server有时候并不能满足所有需要的列。为了满足查询,它必须使用覆盖索引和聚集索引,并且(简化一点)涉及的操作越多,查询成本就越高。

它估计扫描一个索引(聚集索引)比使用两个索引便宜,你得到一个聚集索引扫描的计划。

Here是一篇文章,它进一步讨论了它,以及SQL Server将在何处使用覆盖索引和聚集索引。

+0

我依稀记得布伦特·奥扎尔有一篇关于覆盖索引的更好的文章,为什么他们有时会被忽略,但我找不到它。 –

1

这可能是你的统计数据没有及时更新。您可以使用查询提示来强制SQL Server使用您的首选索引,例如(index(your_index_name))。我会建议尝试这个查询提示来检查你的索引的性能。