风景
CREATE VIEW [dbo].[vProductList]
WITH SCHEMABINDING
AS
SELECT
p.[Id]
,p.[Name]
,price.[Value] as CalculatedPrice
,orders.[Value] as OrdersWithThisProduct
FROM
products as p
INNER JOIN productMetadata as price ON p.Id = price.ProductId AND price.MetaId = 1
INNER JOIN productMetadata as orders ON p.Id = orders.ProductId AND orders.MetaId = 2
为简单起见,假设productMetadata
has 列ProductId, MetaId, Value
有大约 87m 行,并且表中有大约 400k 行products
。
针对此视图的一般查询非常有效:
SELECT * FROM vProductList WHERE CalculatedPrice > 500
查询结果在 2-4 秒内(通过 vpn 和远程,所以我很擅长)。
将上述更改为计数同样快:
SELECT COUNT(*) from vProductList WHERE CalculatedPrice > 500
与原始选择大约在同一时间运行,我再次同意。大约有 10k 种产品符合此标准。
我遇到了两个不同的情况,事情变得非常奇怪并且永远持续下去。
第一的
对视图中基表中的一列进行查询:
SELECT * FROM vProductList WHERE Name = 'Hammer'
这个查询需要一点时间来运行(20-30 秒)并返回大约 30k 的结果;但是,对所述查询稍作更改:
SELECT COUNT(*) FROM vProductList WHERE Name = 'Hammer'
需要 13 分钟才能返回一个说明 ~30k 的计数。
第二
执行WHERE IN
子查询
SELECT * FROM vProductList WHERE Id IN (SELECT ProductId FROM TableThatHasFKToProductId and ColumnInTable = 'Yes')
此查询返回约 300k 行,需要两分钟才能返回(我相信大部分时间只是花在将数据下载到 SSMS 中);但是,将其更改为SELECT COUNT(*)
需要 20 分钟的查询。
SELECT COUNT(*) FROM vProductList WHERE Id IN (SELECT ProductId FROM TableThatHasFKToProductId and ColumnInTable = 'Yes')
为什么它SELECT *
比 快SELECT COUNT
?
我将 SSMS 提供的总执行时间用于此处列出的所有时间。
执行计划
注意:我尝试使用 PasteThePlan,但它一直告诉我的计划是无效的 xml。