SQL Server计划:索引扫描/索引查找之间的区别

在SQL Server执行计划中,索引扫描和索引search有什么区别

我在SQL Server 2005上。

索引扫描是SQL服务器读取整个索引以查找匹配项的时间,这个时间与索引的大小成正比。

索引查找是SQL服务器使用索引的b-tree结构直接查找匹配logging的地方(请参阅http://mattfleming.com/node/192关于这是如何工作的想法); – 所花费的时间只与匹配logging的数量。

  • 一般来说,索引search优于索引扫描(当匹配logging的数量远远低于logging总数时),因为执行索引search所花费的时间是恒定的,而不pipe您的logging中的logging数是多less表。
  • 但是请注意,在某些情况下,索引扫描可能比索引查找更快(有时显着更快) – 通常当表非常小时,或者大部分logging匹配谓词时。

遵循的基本原则是扫描不好,寻求好。

索引扫描

当SQL Server执行扫描时,它将要从磁盘读取的对象加载到内存中,然后从上到下读取该对象,以查找所需的logging。

索引寻求

当SQL Server进行查找时,它知道索引中的数据将在哪里,因此它从磁盘加载索引,直接到它所需的索引部分,并读取到它需要的数据结束。 这显然比扫描更高效,因为SQL已经知道它正在查找的数据在哪里。


如何修改执行计划以使用Seek而不是Scan?

当SQL Server正在查找数据时,可能会使SQL Server从查找切换到扫描的最大的事情之一是当您查找的某些列未包含在要使用的索引中时。 大多数情况下,这将使SQL Server退回到执行聚簇索引扫描,因为聚簇索引包含表中的所有列。 这是最重要的原因之一(至less在我看来),我们现在可以在一个索引中包含INCLUDE列,而不必将这些列添加到索引的索引列中。 通过在索引中包含额外的列,我们增加了索引的大小,但是我们允许SQL Server读取索引,而不必返回到聚集索引,或者它自己获取这些值。

参考

有关SQL Server执行计划中每个操作符的详细信息,请参阅….

  • 集群索引扫描 – 联机丛书

  • 聚集索引寻求 – 书籍
    线上

使用索引扫描,将扫描索引中的所有行以查找匹配的行。 这对于小型表格可以是有效的。 使用索引查找,只需触及实际符合条件的行,因此通常具有更高的性能

扫描与寻找


索引扫描:

由于扫描触及表中的每一行,无论其是否合格,成本与表中的总行数成比例。 因此,如果表格很小或者大多数行符合谓词,则扫描是一种有效的策略。

索引寻求:

由于seek只会触及符合条件的行和包含这些符合条件的行的页面,所以成本与符合条件的行和页的数量成正比,而不是与表中的总行数成比例。

索引扫描不过是扫描从第一页到最后一页的数据页。 如果表上有一个索引,并且如果查询触及大量的数据,这意味着查询正在检索超过50%或90%的数据,然后优化器将只扫描所有数据页检索数据行。 如果没有索引,则可能会在执行计划中看到表扫描(索引扫描)。

索引查找通常是高度select性查询的首选。 这意味着查询只需要更less数量的行,或者只是获取表中其他10行(某些文档占15%)。

通常,查询优化器会尝试使用索引查找,这意味着优化程序find了一个有用的索引来检索logging集。 但是,如果因为在表上没有索引或没有有用的索引而无法这样做,那么SQL Server必须扫描所有满足查询条件的logging。

扫描和查找之间的区别?

扫描将返回整个表或索引。 search有效地根据谓词从索引的一个或多个范围返回行。 例如,请考虑以下查询:

select OrderDate from Orders where OrderKey = 2 

扫描

通过扫描,我们读取订单表中的每一行,评估谓词“where OrderKey = 2”,如果谓词为真(即,如果行限定),则返回行。 在这种情况下,我们将谓词称为“残差”谓词。 为了使性能最大化,只要有可能,我们在扫描中评估残差谓词。 但是,如果谓词过于昂贵,我们可能会在单独的filter迭代器中对其进行评估。 剩余的谓词出现在带有WHERE关键字的文本showplan中或带有标签的XML showplan中。

以下是使用扫描查询该文本的showplan(为简洁起见,稍作编辑):

| – 表扫描(OBJECT:([ORDER]),其中:([ORDERKEY] =(2)))

下图说明了扫描:

在这里输入图像说明

由于扫描触及表中的每一行,无论其是否合格,成本与表中的总行数成比例。 因此,如果表格很小或者大多数行符合谓词,则扫描是一种有效的策略。 但是,如果表很大,并且大多数行不符合条件,则会触及更多的页面和行,并执行比所需更多的I / O操作。

寻求

回到这个例子,如果我们有一个OrderKey的索引,一个seek可能是一个更好的计划。 通过查找,我们使用索引直接导航到满足谓词的那些行。 在这种情况下,我们将谓词称为“寻找”谓词。 在大多数情况下,我们不需要将求谓词重新评估为残差谓词; 该索引确保seek只返回符合条件的行。 seek谓词出现在带有SEEK关键字的文本showplan中,或者带有标签的XML showplan中。

以下是使用seek查询相同查询的文本showplan:

| -Index Seek(OBJECT:([ORDERS]。[OKEY_IDX]),SEEK:([ORDERKEY] =(2))ORDERED FORWARD)

下图说明了查找:

在这里输入图像说明

由于seek只会触及符合条件的行和包含这些符合条件的行的页面,所以成本与符合条件的行和页的数量成正比,而不是与表中的总行数成比例。 因此,如果我们有一个高度select性的查找谓词,寻找通常是一个更有效的策略。 也就是说,如果我们有一个查找谓词消除了大部分表格。

关于showplan的说明

在showplan中,我们区分扫描和查找以及堆(堆没有索引的对象),聚簇索引和非聚簇索引之间的扫描。 下表显示了所有有效的组合:

在这里输入图像说明

https://blogs.msdn.microsoft.com/craigfr/tag/scans-and-seeks/

简短的回答:

  • 索引扫描:触摸所有的行,但某些列。

  • 索引查找:触摸某些行和某些列。

扫描触及表格中的每一行,即使它是否在后面

扫描仅查看您正在查找的行。

寻找总是比扫描更好,因为它们的数据看起来更有效率。

一个很好的解释可以在这里find

索引扫描发生在索引定义无法在单个行上find以满足search谓词时。 在这种情况下,SQL Server必须扫描多个页面才能find满足search谓词的一系列行。

在索引查找的情况下,SQL Server使用索引定义查找单个匹配search谓词的行。

索引search更好,更有效。