[英]SQL Server query performance - removing need for Hash Match (Inner Join)
我有以下查询,它做的很少,并且是我在整个系统中进行的连接类型的示例。
select t1.PrimaryKeyId, t1.AdditionalColumnId
from TableOne t1
join TableTwo t2 on t1.ForeignKeyId = t2.PrimaryKeyId
join TableThree t3 on t1.PrimaryKeyId = t3.ForeignKeyId
join TableFour t4 on t3.ForeignKeyId = t4.PrimaryKeyId
join TableFive t5 on t4.ForeignKeyId = t5.PrimaryKeyId
where
t1.StatusId = 1
and t5.TypeId = 68
所有连接列都有索引,但性能不是很好。 检查查询计划时会发现很多哈希匹配(内部联接),当我真的想要看到嵌套循环连接时。
每个表中的记录数如下:
select count(*) from TableOne
= 64393
select count(*) from TableTwo
= 87245
select count(*) from TableThree
= 97141
select count(*) from TableFour
= 116480
select count(*) from TableFive
= 62
提高此类查询性能的最佳方法是什么?
初步想法:
我不担心你的加入方法......
就个人而言,我从未使用过JOIN提示。 它们仅适用于您在该时间点拥有的数据,索引和统计信息。 随着这些更改,您的JOIN提示会限制优化器
select t1.PrimaryKeyId, t1.AdditionalColumnId
from
TableOne t1
where
t1.Status = 1
AND EXISTS (SELECT *
FROM
TableThree t3
join TableFour t4 on t3.ForeignKeyId = t4.PrimaryKeyId
join TableFive t5 on t4.ForeignKeyId = t5.PrimaryKeyId
WHERE
t1.PrimaryKeyId = t3.ForeignKeyId
AND
t5.TypeId = 68)
AND EXISTS (SELECT *
FROM
TableTwo t2
WHERE
t1.ForeignKeyId = t2.PrimaryKeyId)
tableOne的索引..其中之一
(Status, ForeignKeyId) INCLUDE (AdditionalColumnId)
(ForeignKeyId, Status) INCLUDE (AdditionalColumnId)
tableFive的索引...可能(typeID, PrimaryKeyId)
编辑:更新了JOINS和EXISTS以匹配问题修复
SQL Server非常擅长优化查询,但它也很保守:它可以优化最坏情况下的查询。 循环连接通常会导致索引查找和每行的书签查找。 由于循环连接会导致大型集合的显着降级,因此SQL Server对使用它们犹豫不决,除非它确定行数。
您可以使用forceseek
查询提示强制索引查找:
inner join TableTwo t2 with (FORCESEEK) on t1.ForeignKeyId = t2.PrimaryKeyId
或者,您可以使用loop
关键字强制循环连接:
inner LOOP join TableTwo t2 on t1.ForeignKeyId = t2.PrimaryKeyId
查询提示限制了SQL Server的自由,因此它无法再适应变化的环境。 最佳做法是避免查询提示,除非没有它们就无法满足业务需求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.