在SQL Server中的同一列上创建多个非聚集索引

时间:2014-01-31 10:04:23

标签: sql-server sql-server-2008 sql-server-2005 sql-server-2008-r2 sql-server-2012

什么是索引创建策略?

是否可以在SQL Server的同一列上创建多个非聚集索引?

如何在同一列上创建群集和非群集?

非常抱歉,但索引对我来说非常混乱。

有没有办法找出SQL Server中估计的查询执行时间?

2 个答案:

答案 0 :(得分:3)

这些词语非常符合逻辑,你会很快学会它们。 :)

通俗地说,SEEK意味着寻找记录的精确位置,这就是SQL Server在您搜索的列被编入索引时所做的事情,并且您的过滤器(WHERE条件)足够适合。

SCAN意味着更大范围的行,其中查询执行计划程序估计获取整个范围的速度更快,而不是单独搜索每个值。

是的,您可以在同一个字段上拥有多个索引,有时这可能是一个非常好的主意。播放索引并使用查询执行计划程序确定发生了什么(SSMS中的快捷键:Ctrl + M)。您甚至可以运行同一查询的两个版本,执行计划员可以轻松地向您显示每个版本需要多少资源和时间,从而使优化变得非常简单。

但是为了扩展这些,请说你有一个这样的地址表,它有超过10亿条记录:

CREATE TABLE ADDRESS 
  (ADDRESS_ID INT -- CLUSTERED primary key ADRESS_PK_IDX
  , PERSON_ID INT -- FOREIGN KEY, NONCLUSTERED INDEX ADDRESS_PERSON_IDX
  , CITY VARCHAR(256)
  , MARKED_FOR_CHECKUP BIT
  , **+n^10 different other columns...**)

现在,如果您想查找人12345的所有地址信息,PERSON_ID上的索引就是完美的。由于该表在同一行上有大量其他数据,因此创建非聚集索引以覆盖所有其他列以及PERSON_ID将是低效且占用空间的。在这种情况下,SQL Server将在PERSON_ID中的索引上执行索引SEEK,然后使用它在ADDRESS_ID中的聚簇索引上执行密钥查找,并从那里返回同一行中所有其他列中的所有数据。

但是,假设您要搜索城市中的所有人员,但您不需要其他地址信息。这一次,最有效的方法是在CITY上创建索引并使用INCLUDE选项来覆盖PERSON_ID。这样,单个索引查找/扫描将返回您需要的所有信息,而无需为同一行上的PERSON_ID数据检查CLUSTERED索引。

现在,假设这两个查询都是必需的,但由于10亿条记录,这些查询仍然很重要。但是有一个特殊的查询需要非常快。该查询需要所有已经过MARKED_FOR_CHECKUP的地址的人,以及必须住在纽约的人(忽略任何检查意味着,这无关紧要)。现在你可能想要在MARKED_FOR_CHECKUP和CITY上创建第三个过滤索引,INCLUDE覆盖PERSON_ID,过滤器说CITY ='New York'和MARKED_FOR_CHECKUP = 1.这个索引会非常快,因为它只会覆盖查询满足那些确切条件,因此与其他索引相比,其中有一小部分数据需要通过。

(免责声明,请记住,查询执行计划器不是傻瓜,它可以一起使用多个非聚簇索引来产生正确的结果,所以上面的例子可能不是最好的,因为很难想象什么时候你需要3个不同的索引覆盖同一列,但我相信你明白了。)

索引的类型,列,包括列,排序顺序,过滤器等完全取决于具体情况。您需要制作覆盖索引以满足几种不同类型的查询,以及专门为单个重要查询创建的自定义索引。每个索引都会占用硬盘上的空间,因此制作无用的索引是浪费的,每当数据模型发生变化时都需要额外的维护,并且在碎片整理和统计更新操作中浪费时间......所以你不想只是在所有内容上打一个索引任

实验,学习和解决哪种方法最适合您的需求。

答案 1 :(得分:1)

我也不是索引专家,但这就是我所知道的。

要记住的一个非常重要的一点是索引虽然它使您的选择更快,但影响您的插入/更新/删除速度,因为需要将信息添加到索引,这意味着您在列上的索引越多得到更新,将大大降低更新的速度。

您可以在一个或多个NON-CLUSTERED索引中包含CLUSTERED索引上使用的列。

以下是一些阅读材料

http://www.sqlteam.com/article/sql-server-indexes-the-basics http://www.programmerinterview.com/index.php/database-sql/what-is-an-index/

修改

要记住的另一点是索引占用空间就像表一样。创建的索引越多,它使用的空间就越多,所以尽量不要在索引中使用char / varchar(或nchar / nvarchar)。它用于索引中的大量空间,而在巨大的列上基本上没有任何好处。当您的索引开始变得比您的表更大时,这也意味着您必须重新查看索引策略。