2017-01-26 65 views
2

该查询(SQL2012)执行计划显示我,聚集索引扫描在内部子查询中使用对PK指数:为什么在此查询中使用聚簇索引扫描?

SELECT n3.id as node_id,x.id as id, 
    (select xv.value from xv 
    --with(forceseek) 
    where xv.id=x.id) as [value] 
    FROM x 
    INNER JOIN n3 
    ON x.[obj_id]=n3.id 
    AND n3.parent_id = '975422E0-5630-4545-8CF7-062D7DF72B6B' 

的表格x和XV是主 - >细节的表格。

当我使用提示forceseek时,它显示聚集索引查找和查询执行速度很快。 为什么有Scan而不是Seek? 如何更改查询以使索引搜索没有提示FORCESEEK?

UPD: 完整的演示脚本:

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 
/* 
DROP TABLE [dbo].[xv] 
DROP TABLE [dbo].[x] 
DROP TABLE [dbo].[n3] 
*/ 

CREATE TABLE [dbo].[n3](
    [id] [uniqueidentifier] NOT NULL, 
    [parent_id] [uniqueidentifier] NOT NULL, 
CONSTRAINT [PK_n3] PRIMARY KEY CLUSTERED 
(
    [id] ASC 
) 
) 

GO 

CREATE TABLE [dbo].[x](
    [obj_id] [uniqueidentifier] NOT NULL, 
    [id] [int] IDENTITY(1,1) NOT NULL, 
CONSTRAINT [PK_x] PRIMARY KEY CLUSTERED 
(
    [id] ASC 
)) 

GO 

ALTER TABLE [dbo].[x] WITH CHECK ADD CONSTRAINT [FK_x_n3] FOREIGN KEY([obj_id]) 
REFERENCES [dbo].[n3] ([id]) 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[x] CHECK CONSTRAINT [FK_x_n3] 
GO 

CREATE TABLE [dbo].[xv](
    [id] [int] NOT NULL, 
    [value] [sql_variant] NOT NULL, 
CONSTRAINT [PK_xv] PRIMARY KEY CLUSTERED 
(
    [id] ASC 
)) 

GO 

ALTER TABLE [dbo].[xv] WITH CHECK ADD CONSTRAINT [FK_xv_x] FOREIGN KEY([id]) 
REFERENCES [dbo].[x] ([id]) 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[xv] CHECK CONSTRAINT [FK_xv_x] 
GO 

INSERT INTO n3(id,parent_id) 
select newid(), '975422E0-5630-4545-8CF7-062D7DF72B6B' 
GO 10 

INSERT INTO n3(id,parent_id) 
select newid(), '805422E0-5630-4545-8CF7-062D7DF72B6B' 
GO 5 

INSERT INTO x([obj_id]) 
select id from n3 where parent_id='975422E0-5630-4545-8CF7-062D7DF72B6B'; 


insert into xv (id, value) 
select id, cast(RAND(1) as sql_variant) from x 

--select * from x 
--select * from n3 

    SELECT n3.id as node_id,x.id as id, 
    (select xv.value from dbo.xv 
    --with(forceseek) 
    where xv.id=x.id 
) as [value] 
    FROM dbo.x 
    INNER JOIN dbo.n3 
    ON x.[obj_id]=n3.id 
    AND n3.parent_id = '975422E0-5630-4545-8CF7-062D7DF72B6B' 


/* 
DROP TABLE [dbo].[xv] 
DROP TABLE [dbo].[x] 
DROP TABLE [dbo].[n3] 
*/ 

--Update statistics xv with fullscan 
+0

如果您正在与表中的每一行进行交互,我会想象查询优化器将使用扫描搜索。另外,如果您复制/粘贴查询并同时运行这两个查询,一个使用forceseek,另一个使用它,您将看到扫描的相对成本较低。 – dfundako

+0

真实表中有10 * 100万行。我的问题是,真正的查询(扫描)执行3-5秒,这是死锁的原因。如果我使用提示FORCESEEK,它会工作<1秒,死锁消失。 – Oleg

回答

1

我怀疑statisticsxv的表可能是过时的。更新xv的统计信息并尝试再次运行查询。

Update statistics xv with fullscan 

更新:

看数据建立和查询后,对于给定的parent_id输入是很清楚,在这两种xxv匹配的所有记录,这样很明显,优化选择索引扫描,而不是寻找,因为它已经从xxv获取所有记录表

此外,记录数量更少,所以优化器将更喜欢扫描而不是查找

+0

我试过了 - 没有变化。我已经添加了完整的演示脚本(参见第1条消息),它在3个新表格上演示了这一点。 – Oleg

+0

@Oleg - 检查更新 –

+0

请参阅我上面的评论。 – Oleg

相关问题