A criação de uma cama de teste reconhecidamente bastante simples no SQL Server 2012 (11.0.6020) permite recriar um plano com duas consultas correspondentes a hash sendo concatenadas por meio de a UNION ALL
. Minha cama de teste não exibe a estimativa incorreta que você vê. Talvez este seja um problema do SQL Server 2014 CE.
Eu recebo uma estimativa de 133.785 linhas para uma consulta que realmente retorna 280 linhas, no entanto, isso é esperado, como veremos mais adiante:
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;
Eu acho que o motivo está relacionado à falta de estatísticas para as duas junções resultantes que são UNIONADAS. O SQL Server precisa adivinhar, na maioria dos casos, a seletividade das colunas diante da falta de estatísticas.
Joe Sack tem uma leitura interessante sobre isso aqui .
Para um UNION ALL
, é seguro dizer que veremos exatamente o número total de linhas retornadas por cada componente da união, no entanto, como o SQL Server está usando estimativas de linha para os dois componentes do UNION ALL
, vemos que ele adiciona o total estimado de linhas de ambos consultas para apresentar a estimativa para o operador de concatenação.
No meu exemplo acima, o número estimado de linhas para cada parte do UNION ALL
é 66,8927, que quando somados é igual a 133.785, o que vemos para o número estimado de linhas para o operador de concatenação.
O plano de execução real da consulta de união acima se parece com:
Você pode ver o número "estimado" vs "real" de linhas. No meu caso, adicionar o número "estimado" de linhas retornadas pelos dois operadores de correspondência de hash é exatamente igual à quantidade mostrada pelo operador de concatenação.
Gostaria de tentar obter saída do rastreamento 2363 etc, conforme recomendado no post de Paul White, que você mostra na sua pergunta. Como alternativa, você pode tentar usar OPTION (QUERYTRACEON 9481)
a consulta para reverter para a versão 70 CE e verificar se isso "corrige" o problema.