我有这个查询......运行速度非常慢(几乎一分钟):
select distinct main.PrimeId
from PRIME main
join
(
select distinct p.PrimeId from PRIME p
left outer join ATTRGROUP a
on p.PrimeId = a.PrimeId or p.PrimeId = a.RelatedPrimeId
where a.PrimeId is not null and a.RelatedPrimeId is not null
) mem
on main.PrimeId = mem.PrimeId
PRIME 表有 18k 行,并且在 PrimeId 上有 PK。
ATTRGROUP 表有 24k 行,并且在 PrimeId、col2、RelatedPrimeId、列 4-7 上有复合 PK。在RelatedPrimeId 上还有一个单独的索引。
查询最终返回 8.5k 行 - PRIME 表上 PrimeId 的不同值与 ATTRGROUP 表上的 PrimeId 或 RelatedPrimeId 匹配
我有相同的查询,使用 ATTRADDRESS 而不是 ATRGROUP。 ATTRADDRESS 具有与 ATRGROUP 相同的键和索引结构。它只有 11k 行,诚然,它较小,但在这种情况下,查询运行大约一秒,并返回 11k 行。
所以我的问题是这样的:
尽管结构相同,但一个表上的查询怎么会比另一个表慢这么多。
到目前为止,我已经在 SQL 2005 和(使用相同的数据库,已升级)SQL 2008 R2 上尝试过此操作。我们两个人独立获得了相同的结果,将相同的备份恢复到两台不同的计算机。
其他详细信息:
- 即使在慢速查询中,括号内的位也能在不到一秒的时间内运行
- 执行计划中可能有一条线索,但我不明白。这是其中的一部分,其中包含可疑的 320,000,000 行操作:
但是,该表的实际行数略高于 24k,而不是 320M!
如果我重构括号内的查询部分,以便它使用 UNION 而不是 OR,则:
select distinct main.PrimeId
from PRIME main
join
(
select distinct p.PrimeId from PRIME p
left outer join ATTRGROUP a
on p.PrimeId = a.PrimeId
where a.PrimeId is not null and a.RelatedPrimeId is not null
UNION
select distinct p.PrimeId from PRIME p
left outer join ATTRGROUP a
on p.PrimeId = a.RelatedPrimeId
where a.PrimeId is not null and a.RelatedPrimeId is not null
) mem
on main.PrimeId = mem.PrimeId
...那么慢查询需要不到一秒的时间。
如果您对此有任何见解,我将不胜感激!如果您需要更多信息,请告诉我,我会更新问题。谢谢!
顺便说一句,我意识到在这个例子中存在冗余连接。这不能轻易删除,因为在生产中整个事情都是动态生成的,并且括号中的位有许多不同的形式。
<小时/>编辑:
我已经在 ATTRGROUP 上重建了索引,没有显着差异。
编辑 2:
如果我使用临时表,则:
select distinct p.PrimeId into #temp
from PRIME p
left outer join ATTRGROUP a
on p.PrimeId = a.PrimeId or p.PrimeId = a.RelatedPrimeId
where a.PrimeId is not null and a.RelatedPrimeId is not null
select distinct main.PrimeId
from Prime main join
#temp mem
on main.PrimeId = mem.PrimeId
...话又说回来,即使在原始 OUTER JOIN 中使用 OR,它的运行时间也不会超过一秒。我讨厌这样的临时表,因为它总是感觉像是承认失败,所以这不是我将使用的重构,但我认为它会产生如此大的差异,这很有趣。
编辑3:
更新统计数据也没有什么区别。
感谢您迄今为止提出的所有建议。
最佳答案
根据我的经验,在 JOIN 子句中最好使用两个左连接而不是 OR。 所以代替:
left outer join ATTRGROUP a
on p.PrimeId = a.PrimeId or p.PrimeId = a.RelatedPrimeId
我建议:
left outer join ATTRGROUP a
on p.PrimeId = a.PrimeId
left outer join ATTRGROUP a2
on p.PrimeId = a2.RelatedPrimeId
关于sql-server - 为什么一个查询非常慢,但相似表上的相同查询却眨眼间就运行完毕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7037116/