我最近问了一个关于CTE和使用没有真正根记录的数据的问题(即代替具有NULL parent_Id的根记录,它本身就是父级)
问题链接在这里; Creating a recursive CTE with no rootrecord
答案已经提供给了这个问题,我现在掌握了我需要的数据,但是我对我认为可以使用的两种方法之间的区别感兴趣。
产生我需要的数据的方法是创建一个临时表,其中清理了父数据,然后运行递归CTE。这看起来如下;
Select CASE
WHEN Parent_Id = Party_Id THEN NULL
ELSE Parent_Id
END AS Act_Parent_Id
, Party_Id
, PARTY_CODE
, PARTY_NAME
INTO #Parties
FROM DIMENSION_PARTIES
WHERE CURRENT_RECORD = 1),
WITH linkedParties
AS
(
Select Act_Parent_Id, Party_Id, PARTY_CODE, PARTY_NAME, 0 AS LEVEL
FROM #Parties
WHERE Act_Parent_Id IS NULL
UNION ALL
Select p.Act_Parent_Id, p.Party_Id, p.PARTY_CODE, p.PARTY_NAME, Level + 1
FROM #Parties p
inner join
linkedParties t on p.Act_Parent_Id = t.Party_Id
)
Select *
FROM linkedParties
Order By Level
我还尝试通过定义两个CTE来检索相同的数据。一个用于模拟上面的临时表的创建,另一个用于执行相同的递归工作,但引用初始CTE而不是临时表;
WITH Parties
AS
(Select CASE
WHEN Parent_Id = Party_Id THEN NULL
ELSE Parent_Id
END AS Act_Parent_Id
, Party_Id
, PARTY_CODE
, PARTY_NAME
FROM DIMENSION_PARTIES
WHERE CURRENT_RECORD = 1),
linkedParties
AS
(
Select Act_Parent_Id, Party_Id, PARTY_CODE, PARTY_NAME, 0 AS LEVEL
FROM Parties
WHERE Act_Parent_Id IS NULL
UNION ALL
Select p.Act_Parent_Id, p.Party_Id, p.PARTY_CODE, p.PARTY_NAME, Level + 1
FROM Parties p
inner join
linkedParties t on p.Act_Parent_Id = t.Party_Id
)
Select *
FROM linkedParties
Order By Level
现在这两个脚本在同一台服务器上运行,但临时表方法在大约15秒内产生结果。
多次CTE方法耗时超过5分钟(事实上,我从未等待结果返回)。
为什么临时表方法会更快?
值得我相信它与记录计数有关。基表中有200k记录,从内存中处理大数据集时CTE性能严重下降,但我似乎无法证明我认为我会向专家查询。
非常感谢
答案 0 :(得分:0)
因为似乎没有明确的答案,对该主题的泛型的进一步研究引发了许多具有类似问题的其他线索。
这个似乎涵盖了临时表和CTE之间的许多变化,因此对于那些希望阅读其问题的人来说非常有用;
Which are more performant, CTE or temporary tables?
在我的情况下,我的CTE中的大量数据似乎会引起问题,因为它没有在任何地方缓存,因此每次引用它时都会重新创建它会产生很大的影响。
答案 1 :(得分:0)
这可能与您遇到的问题不完全相同,但我几天前遇到过类似的问题,查询甚至没有处理那么多记录(几千条记录)。
昨天我的同事遇到了类似的问题。
要明确我们正在使用SQL Server 2008 R2。
我发现并且似乎将sql server优化器抛出轨道的模式是在CTE中使用临时表,这些表与主select语句中的其他临时表连接。
在我的情况下,我最终创建了一个额外的临时表。
以下是一个示例。
我最终这样做了:
SELECT DISTINCT st.field1, st.field2
into #Temp1
FROM SomeTable st
WHERE st.field3 <> 0
select x.field1, x.field2
FROM #Temp1 x inner join #Temp2 o
on x.field1 = o.field1
order by 1, 2
我尝试了以下查询,但如果你能相信的话,那么很多就会慢一点。
with temp1 as (
DISTINCT st.field1, st.field2
FROM SomeTable st
WHERE st.field3 <> 0
)
select x.field1, x.field2
FROM temp1 x inner join #Temp2 o
on x.field1 = o.field1
order by 1, 2
我还尝试在第二个查询中内联第一个查询,性能相同,即非常糟糕。
SQL Server永远不会让我感到惊讶。偶尔我会遇到像这样的问题,这些问题让我想起它毕竟是微软产品,但最后你可以说其他数据库系统都有自己的怪癖。