Ani*_*van 6 sql-server parallelism check-constraints computed-column
引用Erik Darling 在我最喜欢的 SQL Server 大师 Brent Ozar 的网站上发表的这篇博客文章:
当您单独从该表中进行选择时,它会显示“ CouldNotGenerateValidParallelPlan ”。
但是,当您将该表连接到另一个没有调用标量 UDF 的检查约束/计算列的表时,查询与“ Good Enough Plan Found ”并行
USE tempdb;
SET NOCOUNT ON;
SELECT TOP 10000
ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )) AS ID, DATEADD(MINUTE, m.message_id, SYSDATETIME()) AS SomeDate
INTO dbo.constraint_test_1
FROM sys.messages AS m, sys.messages AS m2;
GO
SELECT TOP 10000
ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )) AS ID, DATEADD(MINUTE, m.message_id, SYSDATETIME()) AS SomeDate
INTO dbo.constraint_test_2
FROM sys.messages AS m, sys.messages AS m2;
GO
CREATE FUNCTION dbo.DateCheck ( @d DATETIME2(7))
RETURNS BIT
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
DECLARE @Out BIT;
SELECT @Out = CASE WHEN @d < DATEADD(DAY, 30, SYSDATETIME()) THEN 1 ELSE 0 END;
RETURN @Out;
END;
GO
ALTER TABLE dbo.constraint_test_1 ADD CONSTRAINT ck_cc_dt CHECK ( dbo.DateCheck(SomeDate) = 1 );
SELECT *
FROM dbo.constraint_test_1
OPTION (QUERYTRACEON 8649, MAXDOP 0, RECOMPILE); -- Does not go parallel
SELECT T1.ID, T2.SomeDate
FROM dbo.constraint_test_1 T1 INNER JOIN
dbo.constraint_test_2 T2 ON T1.ID = T2.ID
OPTION (QUERYTRACEON 8649, MAXDOP 0, RECOMPILE); -- Goes parallel
Run Code Online (Sandbox Code Playgroud)
如果您想要并行性,则需要一个重要的计划,而且优化器必须能够为查询找到有效的并行计划。
例如,修改您的第一个查询(未使用并行性):
SELECT COUNT_BIG(*)
FROM dbo.constraint_test_1
WHERE ID > (SELECT 0)
OPTION (QUERYTRACEON 8649, MAXDOP 0, RECOMPILE); -- Goes parallel
Run Code Online (Sandbox Code Playgroud)
我将 更改SELECT *为SELECT COUNT_BIG(*)那里以避免使用标量 UDF 约束投影列。我还添加了一个WHERE足够复杂的子句,可以跳过琐碎的计划阶段。
由于约束,您的第二个查询(确实是并行的)可以修改为始终串行:
SELECT T1.ID, T2.SomeDate, T1.SomeDate
FROM dbo.constraint_test_1 T1 INNER JOIN
dbo.constraint_test_2 T2 ON T1.ID = T2.ID
OPTION (QUERYTRACEON 8649, MAXDOP 0, RECOMPILE); -- No parallel
Run Code Online (Sandbox Code Playgroud)
我将T1.SomeDate添加到投影列表中,因此查询现在使用有问题的列。当不需要该列时,优化器将忽略对其的约束,因此它可以找到并行计划。
当进程检测到阻止并行性的条件时 ,可以在编译早期添加NonParallelPlanReason显示计划属性。例如,以下查询生成原因ParallelismDisabledByTraceFlag:
SELECT CT.ID
FROM dbo.constraint_test_1 AS CT
OPTION (QUERYTRACEON 8687);
Run Code Online (Sandbox Code Playgroud)
非并行原因的存在并不意味着肯定会以其他方式考虑并行性。优化器仅在简单计划阶段之后考虑并行性,可选搜索 0,并且肯定搜索 1。有关优化器阶段的更多信息,请参阅我的查询优化器深入研究系列。
您在评论中提到您对引用并行标量函数的计算列的行为感兴趣。我在正确保留计算列中对此进行了描述。
最后,这里不是特别关心的问题,但如果您想测试这样的事情,最好在真实的用户数据库而不是tempdb中进行。tempdb中有几处工作方式不同。