Побудова, очевидно, досить простого тестового шару на SQL Server 2012 (11.0.6020), дозволяє мені відтворити план із двома запитами, відповідніми хешу, об'єднаним через UNION ALL
. Мій тестовий шар не відображає неправильну оцінку, яку ви бачите. Можливо , це є проблемою SQL Server 2014 CE.
Я отримую оцінку в 133,785 рядків за запитом, який фактично повертає 280 рядків, однак цього слід очікувати, як ми побачимо далі вниз:
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 потребує освічених здогадок щодо вибірковості стовпців, коли стикається з відсутністю статистики.
Джо Сак цікаво прочитав про це тут .
Для a UNION ALL
, можна сказати, що ми точно побачимо загальну кількість рядків, повернутих кожним компонентом об'єднання, однак, оскільки SQL Server використовує оцінки рядків для двох компонентів UNION ALL
, ми бачимо, що він додає загальну оціночну кількість рядків з обох запити, щоб створити оцінку для оператора конкатенації.
У моєму прикладі вище, орієнтовна кількість рядків для кожної частини значень UNION ALL
становить 66,8927, що при підсумовуванні дорівнює 133,785, що ми бачимо для передбачуваної кількості рядків для оператора конкатенації.
Фактичний план виконання запиту на об'єднання вище виглядає так:
Ви можете бачити "орієнтовну" проти "фактичну" кількість рядків. У моєму випадку додавання "оціночної" кількості рядків, повернених двома операторами хеш-відповідності, точно дорівнює кількості, показаній оператором конкатенації.
Я б спробував отримати висновок від сліду 2363 тощо, як це рекомендовано у публікації Пола Уайта, яку ви показуєте у своєму питанні. Крім того, ви можете спробувати скористатися OPTION (QUERYTRACEON 9481)
в запиті для повернення до версії 70 CE, щоб побачити, чи "це" вирішує проблему.