sql-server – 并行计划中的“实际”行计数不准确
发布时间:2020-12-12 17:00:50 所属栏目:MsSql教程 来源:网络整理
导读:这是一个纯粹的学术问题,它不会导致问题,我只是想听听对这种行为的任何解释. 采取标准问题Itzik Ben-Gan交叉加入CTE计数表: USE [master]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION [dbo].[TallyTable] ( @N INT)RETURNS TABLE WITH S
这是一个纯粹的学术问题,它不会导致问题,我只是想听听对这种行为的任何解释.
采取标准问题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.更奇怪的是,价值不一致,并且因运行而异. COUNT的结果始终是正确的. 再次发出查询,强制执行非并行计划: SELECT COUNT(N) FROM dbo.TallyTable(1000000) tt OPTION (MAXDOP 1) 这次所有运算符都显示正确的“实际”行数. 到目前为止,我在2005SP3和2008R2上尝试了这个,两者都有相同的结果.有什么可能导致这个问题的想法? 解决方法行在内部从生产者传递到消费者线程的数据包(因此是CXPACKET – 类交换数据包),而不是一次一行.交易所内部有一定数量的缓冲.此外,从Gather Streams的消费者端关闭管道的调用必须在控制包中传递回生产者线程.调度和其他内部考虑意味着并行计划始终具有一定的“停止距离”.因此,您经常会看到这种行计数差异,其中实际需要小于子树的整个潜在行集.在这种情况下,TOP将执行带到“早期结束”. 更多信息: Parallel Execution Plans Suck (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |