繁体   English   中英

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

[英]SQL Server Plans : difference between Index Scan / Index Seek

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

我在 SQL Server 2005 上。

索引扫描是 SQL Server 读取整个索引以寻找匹配项的地方 - 这花费的时间与索引的大小成正比。

索引查找是 SQL 服务器使用索引的 b 树结构直接查找匹配记录的地方(有关如何工作的想法,请参见http://mattfleming.com/node/192 ) - 所用时间仅与匹配记录的数量。

  • 一般来说,索引搜索比索引扫描更可取(当匹配记录的数量远低于记录总数时),因为执行索引搜索所花费的时间是恒定的,无论您的记录总数是多少桌子。
  • 但是请注意,在某些情况下,索引扫描可能比索引查找更快(有时快得多)——通常是当表非常小,或者当很大比例的记录与谓词匹配时。

要遵循的基本规则是扫描不好,搜索是好的。

索引扫描

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

索引搜索

当 SQL Server 执行查找时,它知道数据将在索引中的哪个位置,因此它从磁盘加载索引,直接转到它需要的索引部分并读取到它需要的数据结束的位置. 这显然是比扫描更有效的操作,因为 SQL 已经知道它正在寻找的数据所在的位置。


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

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

参考

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

扫描与寻求


索引扫描:

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

索引寻求:

由于搜索仅触及限定行和包含这些限定行的页面,因此成本与合格行和页面的数量成比例,而不是与表中的总行数成比例。

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

索引搜索通常是高选择性查询的首选。 这意味着查询只是请求更少的行数,或只是检索表中行的其他10个(有些文档说15%)。

通常,查询优化器尝试使用索引查找,这意味着优化器已找到一个有用的索引来检索记录集。 但是,如果由于表上没有索引或没有有用索引而无法执行此操作,则SQL Server必须扫描满足查询条件的所有记录。

扫描和搜索之间的区别?

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

select OrderDate from Orders where OrderKey = 2

扫描

通过扫描,我们读取orders表中的每一行,评估谓词“WhereKey = 2”,如果谓词为真(即,如果行符合条件),则返回该行。 在这种情况下,我们将谓词称为“残差”谓词。 为了最大限度地提高性能,我们尽可能评估扫描中的残差谓词。 但是,如果谓词太昂贵,我们可以在单独的过滤器迭代器中对其进行评估。 残差谓词出现在带有WHERE关键字的文本showplan中或带有标记的XML showplan中。

以下是使用扫描的此查询的文本showplan(为了简洁而略微编辑):

| -Table Scan(OBJECT:([ORDERS]),WHERE:([ORDERKEY] =(2)))

下图说明了扫描:

在此输入图像描述

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

寻求

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

以下是使用搜索的同一查询的文本showplan:

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

下图说明了寻求:

在此输入图像描述

由于搜索仅触及限定行和包含这些限定行的页面,因此成本与合格行和页面的数量成比例,而不是与表中的总行数成比例。 因此,如果我们具有高度选择性的搜索谓词,则搜索通常是更有效的策略; 也就是说,如果我们有一个搜索谓词可以消除表的很大一部分。

关于showplan的说明

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

在此输入图像描述

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

简短的回答:

  • 索引扫描:触摸除某些列之外的所有行。

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

使用索引扫描,索引中的所有行都会被扫描以找到匹配的行。 这对于小表来说是有效的。 使用索引查找,它只需要接触实际满足条件的行,因此通常性能更高

当索引定义无法在单行上找到满足搜索谓词时,就会发生索引扫描。 在这种情况下,SQL Server 必须扫描多个页面才能找到满足搜索谓词的行范围

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

索引搜索更好、更有效。

扫描会触及表格中的每一行,即使它是您所追求的

搜索只查看您要查找的行。

搜索总是比扫描更好,因为它们在查找数据的方式上更有效。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM