我在树结构上使用递归 CTE 来列出树中特定节点的所有后代。如果我在我的WHERE子句中写了一个文字节点值,SQL Server 似乎实际上只是将 CTE 应用于该值,给出一个实际行数较低的查询计划,等等:
但是,如果我将该值作为参数传递,它似乎实现了(假脱机)CTE,然后在事后对其进行过滤:
我可能读错了计划。我没有注意到性能问题,但我担心 CTE 的实现可能会导致较大数据集出现问题,尤其是在繁忙的系统中。此外,我通常将这种遍历本身复合:我遍历祖先并返回后代(以确保收集所有相关节点)。由于我的数据如何,每组“相关”节点都相当小,因此实现 CTE 没有意义。当 SQL Server 似乎意识到 CTE 时,它在“实际”计数中给了我一些相当大的数字。
有没有办法让查询的参数化版本表现得像文字版本?我想把 CTE 放在一个可重用的视图中。
用文字查询:
CREATE PROCEDURE #c AS BEGIN;
WITH descendants AS (SELECT
t.ParentId Id
,t.Id DescendantId
FROM #tree t
WHERE t.ParentId IS NOT NULL
UNION ALL SELECT
d.Id
,t.Id DescendantId
FROM descendants d
JOIN #tree t ON d.DescendantId = t.ParentId)
SELECT d.*
FROM descendants d
WHERE d.Id = 24
ORDER BY d.Id, d.DescendantId; …Run Code Online (Sandbox Code Playgroud) 我将SQL Server从2016年升级到2019年,我的查询的查询计划改变了,它使用了自适应连接,但不幸的是查询的持续时间从1秒增加到1分钟,我改变了连接顺序,问题解决了
T-SQL 代码:
SELECT TOP 100 * FROM dbo.APP App
JOIN dbo.PRS p ON App.PartyId=p.PRSId
LEFT JOIN dbo.Country ON p.NationalityId = dbo.Country.CountryId
LEFT JOIN dbo.EDUBranch b ON app.EducationBranchId=b.EDUBranchId
Run Code Online (Sandbox Code Playgroud)
它的查询计划:https : //www.brentozar.com/pastetheplan/?id=H1cFQxwdP
更改连接顺序后:
SELECT TOP 100 * FROM dbo.APP App
LEFT JOIN dbo.EDUBranch b ON app.EducationBranchId=b.EDUBranchId
JOIN dbo.PRS p ON App.PartyId=p.PRSId
LEFT JOIN dbo.Country ON p.NationalityId = dbo.Country.CountryId
Run Code Online (Sandbox Code Playgroud)
它的查询计划:https : //www.brentozar.com/pastetheplan/?id=SJv1GlPdv
有没有人知道
我们有一台新服务器,我们也在迁移它,并希望看到硬件的潜在优势。所以我们的想法是我们捕获工作负载并在我们的新盒子上重放它。
然而,我的问题是关于看到性能优势。我将运行一些性能计数器,但理想情况下,我们希望查看单个查询的速度有多快。
我将在初始工作负载捕获中获取此信息,但是当我在新服务器上重放此信息时,我是否同时需要运行跟踪以捕获新的工作负载信息。实际上同时运行 SQL 探查器两次以进行重放和捕获?