简体   繁体   English

如何在SQL Server中使用Forceseek扫描

[英]How to use forceseek scan in SQL Server

I am using SQL Server 2012. 我正在使用SQL Server 2012。

My queries are: 我的查询是:

create table tab (id int, nm varchar(10))

insert into tab values (1, 'a'), (2, 'b'), (3, 'c')

create index IX_nm on tab(id)
go

create table tab2(id1 int, age int)

insert into tab2 values (1, 21), (2, 22), (3, 54)

create index IX_nm2 on tab2(id1)
go

select * 
from tab a 
inner join tab2 b on a.id = b.id1

select * 
from tab a 
inner join tab2 b with(forceseek) on a.id = b.id1

I have included the execution plans of them. 我已经包括了他们的执行计划。

在此处输入图片说明

在此处输入图片说明

I am not able to differentiate between the 2 queries, and they produce the same execution plan. 我无法区分这两个查询,它们产生相同的执行计划。

There is no difference between the two plans because SQL Server has already chosen to do an Index Seek on tab2.IX_nm2 without the need for the FORCESEEK hint. 两种计划之间没有区别,因为SQL Server已经选择在tab2.IX_nm2上执行索引查找,而无需FORCESEEK提示。

Take a look at the plan produced: 看一下生成的计划:

在此处输入图片说明

You want all rows from tab , so SQL Server does a table scan. 您需要tab 所有行,因此SQL Server进行表扫描。 It won't use IX_nm because it doesn't contain nm and would have to do a lookup to retrieve this column from the heap. 它不会使用IX_nm因为它不包含nm ,并且必须进行查找以从堆中检索此列。 However, you could use a CLUSTERED index which will remove that table scan: 但是,您可以使用CLUSTERED索引来删除该表扫描:

create CLUSTERED index IX_nm on tab(id);

The Nested Loop between The Scan and the Seek basically says, For every row returned by the Table Scan on tab, get me the corresponding row from tab2 based on the ID . “扫描”和“查找”之间的嵌套循环基本上说: For every row returned by the Table Scan on tab, get me the corresponding row from tab2 based on the ID The underlying statistics on IX_nm2 indicates to SQL Server that there is likely to be only one or two rows returned and so it does a Seek for those rows, rather than scans the whole table. IX_nm2上的基础统计信息向SQL Server指示可能仅返回一或两行,因此它对这些行执行“查找”,而不是扫描整个表。

However, because your index is NONCLUSTERED and doesn't include age , SQL Server also has to do a RID Lookup to get the age . 但是,由于索引是NONCLUSTERED且不包含age ,因此SQL Server还必须执行RID查找来获取age Again, you can avoid this by making the index IX_nm2 a CLUSTERED index. 同样,可以通过将索引IX_nm2CLUSTERED索引来避免这种情况。

CREATE clustered index CIX_nm2 on tab2(id1);

This would result in a much simpler plan. 这将导致更简单的计划。

在此处输入图片说明

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

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