【发布时间】:2011-07-18 07:52:06
【问题描述】:
我们有相当大的机器 100GB+ 内存和 8+ 个内核。服务器范围的 MAXDOP=8。
T_SEQ_FF rowcount = 61692209, size = 2991152 KB
UPD 1:
表T_SEQ_FF 有两个索引:
1) create index idx_1 on T_SEQ_FF (first_num)
2) create index idx_2 on T_SEQ_FF (second_num)
表T_SEQ_FF 有first_num、second_num pairs 的nums 应该在cte 之后提供一个序列:
;with first_entity as (
select first_num from T_SEQ_FF a where not exists (select 1 from T_SEQ_FF b where a.first_num = b.second_num)
) ,
cte as (
select a.first_num, a.second_num, a.first_num as first_key, 1 as sequence_count
from T_SEQ_FF a inner join first_entity b on a.first_num = b.first_num
union all
select a.first_num, a.second_num, cte.first_key, cte.sequence_count + 1
from T_SEQ_FF a
inner join cte on a.first_num = cte.second_num
)
select *
from cte
option (maxrecursion 0);
但是当我运行这个查询时 - 我只看到没有并行的串行查询计划。 如果我从上面的查询中删除 CTE 的第二部分:
union all
select a.first_num, a.second_num, cte.first_key, cte.sequence_count + 1
from T_SEQ_FF a
inner join cte on a.first_num = cte.second_num
然后我可以看到查询计划使用 Repartition 和 Gather Streams 变得并行化。
所以我可以总结一下,这是因为 recurisve CTE SQL Server 在处理这个查询时没有使用并行。
我相信在拥有大量免费资源的大型机器上,并行性应该有助于更快地完成查询。
目前它运行约 40-50 分钟。
您能否建议我们如何使用尽可能多的资源来更快地完成查询?
CTE 是唯一的选择,因为我们需要从 first_num - second_num 对中填充序列,而这些序列可以是任意长度。
【问题讨论】:
-
你有关于 T_SEQ_FF.second_num 的索引吗?
-
是的,我已将我们使用的索引创建子句添加到主题中。
-
我猜这是 recursive 部分,而不是 CTE。
-
是的,正是我的错误——我称 CTE 为“递归 CTE”。那么为什么 SQL Server 至少不能并行化 SCAN 表(索引)以进行递归部分的准备步骤?为什么整个查询是串行的。
-
@zmische - 我猜这不是答案,但我认为这是因为第二个查询取决于第一个。由于第二个内部加入了第一个,它们不会同时运行。从效率的角度来看,限制
INNER JOIN返回的行比同时运行两者然后过滤掉无效行更有意义。
标签: sql sql-server performance sql-server-2008