在条件带来执行计划的地方添加虚拟

xyhw6mcr  于 2021-07-29  发布在  Java
关注(0)|答案(2)|浏览(350)

你能看一下吗http://sqlfiddle.com/#!18/7ad28/8,帮助我理解为什么添加where条件会在seek from scan上带来索引?根据我的(错误的)理解,它不应该有任何区别,因为它是一个更大的条件,应该导致扫描。
我还在下面粘贴有问题的表脚本和查询

CREATE TABLE [dbo].[Mappings]
(
[MappingID] [smallint] NOT NULL IDENTITY(1, 1),
[ProductID] [smallint] NOT NULL,
[CategoryID] [smallint] NOT NULL
) 
GO
ALTER TABLE [dbo].[Mappings] ADD CONSTRAINT [pk_Mappings_MappingID] PRIMARY KEY CLUSTERED ([MappingID]) WITH (DATA_COMPRESSION = PAGE) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [nc_Mappings_ProductIDCategoryID] ON [dbo].[Mappings] ([ProductID], [CategoryID]) WITH (DATA_COMPRESSION = PAGE) ON [PRIMARY]
GO

CREATE TABLE [dbo].[CustomerProducts]
(
[CustomerID] [bigint] NOT NULL,
[ProductID] [smallint] NOT NULL,
[SomeDate] [datetimeoffset] (0) NULL,
[SomeAttribute] [bigint] NULL
) 
GO
ALTER TABLE [dbo].[CustomerProducts] ADD CONSTRAINT [pk_CustomerProducts_ProductIDCustomerID] PRIMARY KEY CLUSTERED ([ProductID], [CustomerID]) ON [PRIMARY]
GO

--SCAN [tempdb].[dbo].[Mappings].[nc_Mappings_ProductIDCategoryID].(NonClustered)   
SELECT b.[SomeDate],
       b.[SomeAttribute]
FROM dbo.[Mappings] a
    INNER JOIN dbo.CustomerProducts b
        ON a.[ProductID] = b.[ProductID]
Where b.CustomerID = 88;

--SEEK [tempdb].[dbo].[Mappings].[nc_Mappings_ProductIDCategoryID].(NonClustered)   
SELECT b.[SomeDate],
       b.[SomeAttribute]
FROM dbo.[Mappings] a
    INNER JOIN dbo.CustomerProducts b
        ON a.[ProductID] = b.[ProductID]
           AND b.CustomerID = 88
Where a.[ProductID] > 0;
qco9c6ql

qco9c6ql1#

“它不应该有任何区别,因为它是一个更大的条件,应该导致扫描。”
您添加了一个显式 predicate (productid>0),因此SQLServer选择在该值(0)上查找,然后进行范围扫描。要查看这一点,请选择索引seek on mappings,打开properties选项卡,查找seek predicate ,并展开整个结果树。您将在下面看到开始和适用的范围扫描属性。
所以如果你有真实的数据(假设你有1-100的productid),并且有一个where productid>77。您将在b树中查找productID77,然后对非聚集索引的其余部分进行范围扫描。
注意:这将帮助您可视化和理解不同索引操作中内部发生的事情(免责声明:这是我的演示)https://youtu.be/fdd4lw6dfqu?t=748

dbf7pr2w

dbf7pr2w2#

计划如下:

屏幕上的信息以黄色显示 clustered index seek 从表 CustomerProducts . seek predicate 被设置为条件的值 [ProductID] > 0 作为连接条件的一部分是完全合理的 a.[ProductID] = b.[ProductID] 还有 a.[ProductID] > 0 在where子句中。这意味着 b.[ProductID] > 0 . 作为 ProductID 是聚集索引上的第一列,可以使用任何减少查找的信息。seek操作应该比scan快,因此优化器将尝试这样做。

相关问题