在本演示中,我应该在每列上创建一个索引还是仅在一个非聚集索引上创建索引(Index Scan,Seek)

时间:2018-07-09 04:29:39

标签: sql sql-server

测试DDL:

CREATE TABLE TestTable([col1] varchar(2), [col2] varchar(2), [col3] varchar(2));   
INSERT INTO TestTable ([col1], [col2], [col3]) VALUES ('a1', 'b1', 'c1');

示例1(仅一个非聚集索引):

Create Nonclustered Index Index_TestTable  on  TestTable ([col1], [col2], [col3]) ;

select  [col2], [col3] from TestTable
where  [col2] = 'b1'  ;

结果:

Index Scan

example2(两个非聚集索引):

Create Nonclustered Index Index_TestTable  on  TestTable ([col1], [col2], [col3]) ;
Create Nonclustered Index Index_TestTable2  on  TestTable ([col2], [col1], [col3]) ;
select  [col2], [col3] from TestTable
where  [col2] = 'b1'  ;

结果:

Index Seek

。我应该在每一列上创建一个索引还是仅创建一个索引?

ps。 select .. where col1,col2,col3的列顺序是随机的。

3 个答案:

答案 0 :(得分:1)

如果您总是要使用col2查询表,那么您需要在索引中包含col1和col3,您只需为col2创建一个索引,如下所示:

Create Nonclustered Index Index_TestTable  on  TestTable ([col2]) ;

答案 1 :(得分:1)

您尚未提供有关为什么需要在这些列上建立索引的任何信息,但是根据一般经验,我可以告诉您,在表的每一列上创建索引都不是正确的方法。

非聚集索引可以提高搜索性能,但会对插入/更新/删除操作产生负面影响(并且可能浪费存储空间)。

如果向表中添加新的非聚集索引,则实际上会创建一个新表来维护该索引。例如,如果您在 LastName 列上创建了非聚集索引,那么您将创建一个新表来存储 LastName 的排序列表,并带有指向相应列表的指针行。如果您要在 LastName 上搜索表,这可能会提高性能,但对表更新有负面影响,因为每次更新表时,您也需要更新/排序索引。

非聚集索引只能在您定期搜索的列上创建。

答案 2 :(得分:1)

我完全同意Hooman的评论。但是,我只想解释一下为什么在example2中获得“索引搜索”的原因,

由于TestTable仅包含全部包含在非聚集索引中的三列,因此它们在索引中的顺序导致了差异。

在示例2中,由于索引Index_TestTable2首先具有[col2],因此仅执行单个查找(基于where [col2] = 'b1')。因此,如果在example2中删除索引Index_TestTable,则仍应获得“索引搜索”。有关更多详细信息,请参阅here