在SQL Server 2012(11.0.6020)上构建一个公认非常简单的测试平台,使我可以重新创建一个计划,其中两个哈希匹配查询通过串联UNION ALL
。我的测试台没有显示您看到的错误估计。也许这是 SQL Server 2014 CE问题。
对于一个实际上返回280行的查询,我得到了133.785行的估计,但是这是可以预期的,因为我们将在下面进一步介绍:
IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
Union1_ID INT NOT NULL
CONSTRAINT PK_Union1
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, Union1_Text VARCHAR(255) NOT NULL
, Union1_ObjectID INT NOT NULL
);
IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
Union2_ID INT NOT NULL
CONSTRAINT PK_Union2
PRIMARY KEY CLUSTERED
IDENTITY(2,2)
, Union2_Text VARCHAR(255) NOT NULL
, Union2_ObjectID INT NOT NULL
);
INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO
SELECT *
FROM dbo.Union1 u1
INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;
我认为原因是缺少两个统一的结果联接的统计信息。在缺乏统计信息的情况下,大多数情况下,SQL Server需要围绕列的选择性进行有根据的猜测。
乔·萨克(Joe Sack)在这里对此感兴趣。
对于a UNION ALL
,可以肯定地说,我们将确切地看到联合的每个组件返回的总行数,但是,由于SQL Server 对的两个组件都使用行估计,因此UNION ALL
我们看到它将两个行的总估计行相加查询以得出串联运算符的估计值。
在上面的示例中,每个部分的估计行数UNION ALL
为66.8927,总和等于133.785,对于串联运算符,我们看到了估计行数。
上面的联合查询的实际执行计划如下:
您可以看到“估计”与“实际”的行数。就我而言,将两个哈希匹配运算符返回的“估计”行数相加,就等于串联运算符显示的数量。
我会尝试从问题中显示的Paul White的帖子中建议从跟踪2363等获得输出。或者,您可以尝试OPTION (QUERYTRACEON 9481)
在查询中使用还原到70 CE版本,以查看是否可以“解决”该问题。