我有这个查询......运行速度非常慢(几乎一分钟):
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 和 cols 4-7 上具有复合 PK。RelatedPrimeId 上还有一个单独的索引。
该查询最终返回 8.5k 行 - PRIME 表上与 ATTRGROUP 表上 PrimeId 或 RelatedPrimeId 匹配的不同 PrimeId 值
我有相同的查询,使用 ATTRADDRESS 而不是 ATTRGROUP。ATTRADDRESS 具有与 ATTRGROUP 相同的键和索引结构。它只有 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:
更新统计数据也没有区别。
感谢您迄今为止的所有建议。