微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql-server – 并行计划中的“实际”行计数不准确

这是一个纯粹的学术问题,它不会导致问题,我只是想听听对这种行为的任何解释.

采取标准问题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.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐