加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

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
Understanding and Using Parallelism in SQL Server.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读