简体   繁体   English

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

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

In a SQL Server Execution plan what is the difference between an Index Scan and an Index Seek在 SQL Server 执行计划中,索引扫描和索引查找有什么区别

I'm on SQL Server 2005.我在 SQL Server 2005 上。

An index scan is where SQL server reads the whole of the index looking for matches - the time this takes is proportional to the size of the index.索引扫描是 SQL Server 读取整个索引以寻找匹配项的地方 - 这花费的时间与索引的大小成正比。

An index seek is where SQL server uses the b-tree structure of the index to seek directly to matching records (see http://mattfleming.com/node/192 for an idea on how this works) - time taken is only proportional to the number of matching records.索引查找是 SQL 服务器使用索引的 b 树结构直接查找匹配记录的地方(有关如何工作的想法,请参见http://mattfleming.com/node/192 ) - 所用时间仅与匹配记录的数量。

  • In general an index seek is preferable to an index scan (when the number of matching records is proprtionally much lower than the total number of records), as the time taken to perform an index seek is constant regardless of the toal number of records in your table.一般来说,索引搜索比索引扫描更可取(当匹配记录的数量远低于记录总数时),因为执行索引搜索所花费的时间是恒定的,无论您的记录总数是多少桌子。
  • Note however that in certain situations an index scan can be faster than an index seek (sometimes significantly faster) - usually when the table is very small, or when a large percentage of the records match the predicate.但是请注意,在某些情况下,索引扫描可能比索引查找更快(有时快得多)——通常是当表非常小,或者当很大比例的记录与谓词匹配时。

The basic rule to follow is Scans are bad, Seeks are good.要遵循的基本规则是扫描不好,搜索是好的。

Index Scan索引扫描

When SQL Server does a scan it loads the object which it wants to read from disk into memory, then reads through that object from top to bottom looking for the records that it needs.当 SQL Server 执行扫描时,它将它想要从磁盘读取的对象加载到内存中,然后从上到下读取该对象以查找它需要的记录。

Index Seek索引搜索

When SQL Server does a seek it knows where in the index that the data is going to be, so it loads up the index from disk, goes directly to the part of the index that it needs and reads to where the data that it needs ends.当 SQL Server 执行查找时,它知道数据将在索引中的哪个位置,因此它从磁盘加载索引,直接转到它需要的索引部分并读取到它需要的数据结束的位置. This is obviously a much more efficient operation than a scan, as SQL already knows where the data it is looking for is located.这显然是比扫描更有效的操作,因为 SQL 已经知道它正在寻找的数据所在的位置。


How can I modify an Execution Plan to use a Seek instead of a Scan?如何修改执行计划以使用 Seek 而不是 Scan?

When SQL Server is looking for your data probably one of the largest things which will make SQL Server switch from a seek to a scan is when some of the columns are you looking for are not included in the index you want it to use.当 SQL Server 正在查找您的数据时,可能使 SQL Server 从查找切换到扫描的最大事情之一是您要查找的某些列未包含在您希望它使用的索引中。 Most often this will have SQL Server fall back to doing a clustered index scan, since the Clustered index contains all the columns in the table.大多数情况下,这会让 SQL Server 回退到执行聚集索引扫描,因为聚集索引包含表中的所有列。 This is one of the biggest reasons (in my opinion at least) that we now have the ability to INCLUDE columns in an index, without adding those columns to the indexed columns of the index.这是我们现在能够在索引中包含列的最大原因之一(至少在我看来),而无需将这些列添加到索引的索引列中。 By including the additional columns in the index we increase the size of the index, but we allow SQL Server to read the index, without having togo back to the clustered index, or to the table it self to get these values.通过在索引中包含额外的列,我们增加了索引的大小,但我们允许 SQL Server 读取索引,而不必返回聚集索引或它自己的表来获取这些值。

References参考

For information regarding the specifics of each of these operators within a SQL Server Execution plan see....有关 SQL Server 执行计划中每个运算符的详细信息,请参阅....

Scans vs. Seeks 扫描与寻求


Index Scan: 索引扫描:

Since a scan touches every row in the table, whether or not it qualifies, the cost is proportional to the total number of rows in the table. 由于扫描触及表中的每一行,无论其是否合格,成本都与表中的总行数成比例。 Thus, a scan is an efficient strategy if the table is small or if most of the rows qualify for the predicate. 因此,如果表很小或者大多数行符合谓词的条件,则扫描是一种有效的策略。

Index Seek: 索引寻求:

Since a seek only touches rows that qualify and pages that contain these qualifying rows, the cost is proportional to the number of qualifying rows and pages rather than to the total number of rows in the table. 由于搜索仅触及限定行和包含这些限定行的页面,因此成本与合格行和页面的数量成比例,而不是与表中的总行数成比例。

Index Scan is nothing but scanning on the data pages from the first page to the last page. 索引扫描只是扫描从第一页到最后一页的数据页。 If there is an index on a table, and if the query is touching a larger amount of data, which means the query is retrieving more than 50 percent or 90 percent of the data, and then the optimizer would just scan all the data pages to retrieve the data rows. 如果表上有索引,并且查询触及大量数据,这意味着查询检索的数据超过50%或90%,然后优化器只扫描所有数据页检索数据行。 If there is no index, then you might see a Table Scan (Index Scan) in the execution plan. 如果没有索引,那么您可能会在执行计划中看到表扫描(索引扫描)。

Index seeks are generally preferred for the highly selective queries. 索引搜索通常是高选择性查询的首选。 What that means is that the query is just requesting a fewer number of rows or just retrieving the other 10 (some documents says 15 percent) of the rows of the table. 这意味着查询只是请求更少的行数,或只是检索表中行的其他10个(有些文档说15%)。

In general query optimizer tries to use an Index Seek which means that the optimizer has found a useful index to retrieve record set. 通常,查询优化器尝试使用索引查找,这意味着优化器已找到一个有用的索引来检索记录集。 But if it is not able to do so either because there is no index or no useful indexes on the table, then SQL Server has to scan all the records that satisfy the query condition. 但是,如果由于表上没有索引或没有有用索引而无法执行此操作,则SQL Server必须扫描满足查询条件的所有记录。

Difference between a scan and a seek? 扫描和搜索之间的区别?

A scan returns the entire table or index. 扫描返回整个表或索引。 A seek efficiently returns rows from one or more ranges of an index based on a predicate. 搜索基于谓词有效地从索引的一个或多个范围返回行。 For example, consider the following query: 例如,请考虑以下查询:

select OrderDate from Orders where OrderKey = 2

Scan 扫描

With a scan, we read each row in the orders table, evaluate the predicate “where OrderKey = 2” and, if the predicate is true (ie, if the row qualifies), return the row. 通过扫描,我们读取orders表中的每一行,评估谓词“WhereKey = 2”,如果谓词为真(即,如果行符合条件),则返回该行。 In this case, we refer to the predicate as a “residual” predicate. 在这种情况下,我们将谓词称为“残差”谓词。 To maximize performance, whenever possible we evaluate the residual predicate in the scan. 为了最大限度地提高性能,我们尽可能评估扫描中的残差谓词。 However, if the predicate is too expensive, we may evaluate it in a separate filter iterator. 但是,如果谓词太昂贵,我们可以在单独的过滤器迭代器中对其进行评估。 The residual predicate appears in text showplan with the WHERE keyword or in XML showplan with the tag. 残差谓词出现在带有WHERE关键字的文本showplan中或带有标记的XML showplan中。

Here is the text showplan (slightly edited for brevity) for this query using a scan: 以下是使用扫描的此查询的文本showplan(为了简洁而略微编辑):

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

The following figure illustrates the scan: 下图说明了扫描:

在此输入图像描述

Since a scan touches every row in the table whether or not it qualifies, the cost is proportional to the total number of rows in the table. 由于扫描触及表中的每一行,无论其是否合格,因此成本与表中的总行数成比例。 Thus, a scan is an efficient strategy if the table is small or if most of the rows qualify for the predicate. 因此,如果表很小或者大多数行符合谓词的条件,则扫描是一种有效的策略。 However, if the table is large and if most of the rows do not qualify, we touch many more pages and rows and perform many more I/Os than is necessary. 但是,如果表很大并且大多数行不符合条件,我们会触及更多页面和行,并执行比必要更多的I / O.

Seek 寻求

Going back to the example, if we have an index on OrderKey, a seek may be a better plan. 回到这个例子,如果我们在OrderKey上有一个索引,那么搜索可能是一个更好的计划。 With a seek, we use the index to navigate directly to those rows that satisfy the predicate. 通过搜索,我们使用索引直接导航到满足谓词的那些行。 In this case, we refer to the predicate as a “seek” predicate. 在这种情况下,我们将谓词称为“搜索”谓词。 In most cases, we do not need to re-evaluate the seek predicate as a residual predicate; 在大多数情况下,我们不需要将搜索谓词重新评估为残差谓词; the index ensures that the seek only returns rows that qualify. 索引确保seek只返回符合条件的行。 The seek predicate appears in the text showplan with the SEEK keyword or in XML showplan with the tag. 搜索谓词出现在带有SEEK关键字的文本showplan中或带有标记的XML showplan中。

Here is the text showplan for the same query using a seek: 以下是使用搜索的同一查询的文本showplan:

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

The following figure illustrates the seek: 下图说明了寻求:

在此输入图像描述

Since a seek only touches rows that qualify and pages that contain these qualifying rows, the cost is proportional to the number of qualifying rows and pages rather than to the total number of rows in the table. 由于搜索仅触及限定行和包含这些限定行的页面,因此成本与合格行和页面的数量成比例,而不是与表中的总行数成比例。 Thus, a seek is generally a more efficient strategy if we have a highly selective seek predicate; 因此,如果我们具有高度选择性的搜索谓词,则搜索通常是更有效的策略; that is, if we have a seek predicate that eliminates a large fraction of the table. 也就是说,如果我们有一个搜索谓词可以消除表的很大一部分。

A note about showplan 关于showplan的说明

In showplan, we distinguish between scans and seeks as well as between scans on heaps (an object with no index), clustered indexes, and non-clustered indexes. 在showplan中,我们区分扫描和搜索以及堆上的扫描(没有索引的对象),聚簇索引和非聚簇索引。 The following table shows all of the valid combinations: 下表显示了所有有效组合:

在此输入图像描述

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

Short answer:简短的回答:

  • Index scan: Touch all rows but certain columns.索引扫描:触摸除某些列之外的所有行。

  • Index seek: Touch certain rows and certain columns.索引查找:触摸某些行和某些列。

With an Index Scan, all rows in the index are being scanned to find a matching row.使用索引扫描,索引中的所有行都会被扫描以找到匹配的行。 This can be efficient for small tables.这对于小表来说是有效的。 With an Index Seek, it only needs to touch the rows that actually meet the criteria and so is generally more performant使用索引查找,它只需要接触实际满足条件的行,因此通常性能更高

An Index Scan happens when the index definition cannot find on a single row to satisfy search predicates.当索引定义无法在单行上找到满足搜索谓词时,就会发生索引扫描。 In this case SQL Server has to scan multiple pages to find a range of rows which satisfy the search predicates.在这种情况下,SQL Server 必须扫描多个页面才能找到满足搜索谓词的行范围

In the case of a Index Seek, SQL Server finds a single row matching search predicates using index definition.在索引查找的情况下,SQL Server 使用索引定义查找与搜索谓词匹配的单行。

Index Seeks are better and more effective.索引搜索更好、更有效。

A scan touches every row in the table even if its what you are after or not扫描会触及表格中的每一行,即使它是您所追求的

A seek looks only at the rows that are what you are looking for.搜索只查看您要查找的行。

Seeks are always better to have than scans as they are more efficient in the way it looks data up.搜索总是比扫描更好,因为它们在查找数据的方式上更有效。

A good explanation can be found here一个很好的解释可以在这里找到

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

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