这是一个纯粹的学术问题,它不会引起问题,我只是想听听对这种行为的任何解释。
以标准问题 Itzik Ben-Gan 交叉连接 CTE 计数表为例:
USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[TallyTable]
(
@N INT
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
(
WITH
E1(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 1*10^1 or 10 rows
, E2(N) AS (SELECT 1 FROM E1 a, E1 b) -- 1*10^2 or 100 rows
, E4(N) AS (SELECT 1 FROM E2 a, E2 b) -- 1*10^4 or 10,000 rows
, E8(N) AS (SELECT 1 FROM E4 a, E4 b) -- 1*10^8 or 100,000,000 rows
SELECT TOP (@N) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM E8
)
GO
发出将创建 100 万行编号表的查询:
SELECT
COUNT(N)
FROM
dbo.TallyTable(1000000) tt
看看这个查询的并行执行计划:
请注意,在收集流运算符之前的“实际”行数是 1,004,588。在收集流运算符之后,行数是预期的 1,000,000。更奇怪的是,该值并不一致,并且会因运行而异。COUNT 的结果总是正确的。
再次发出查询,强制执行非并行计划:
SELECT
COUNT(N)
FROM
dbo.TallyTable(1000000) tt
OPTION (MAXDOP 1)
这一次,所有运算符都显示正确的“实际”行数。
到目前为止,我已经在 2005SP3 和 2008R2 上尝试过,两者的结果相同。关于可能导致这种情况的任何想法?