Membangun test bed yang diakui agak sederhana pada SQL Server 2012 (11.0.6020) memungkinkan saya untuk membuat ulang rencana dengan dua query hash yang cocok digabungkan melalui a UNION ALL
. Tempat tidur pengujian saya tidak menampilkan perkiraan yang salah yang Anda lihat. Mungkin ini adalah masalah SQL Server 2014 CE.
Saya mendapatkan perkiraan 133.785 baris untuk kueri yang benar-benar mengembalikan 280 baris, namun itu diharapkan karena kita akan melihat lebih jauh ke bawah:
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;
Saya pikir alasannya adalah sekitar kurangnya statistik untuk dua gabungan yang dihasilkan yang UNIONed. SQL Server perlu membuat tebakan dalam kebanyakan kasus seputar selektivitas kolom ketika dihadapkan dengan kurangnya statistik.
Joe Sack memiliki bacaan yang menarik tentang hal itu di sini .
Untuk a UNION ALL
, aman untuk mengatakan kita akan melihat jumlah total baris yang dikembalikan oleh masing-masing komponen serikat, namun karena SQL Server menggunakan estimasi baris untuk dua komponen UNION ALL
, kita melihatnya menambahkan total estimasi baris dari kedua pertanyaan untuk datang dengan perkiraan untuk operator gabungan.
Dalam contoh saya di atas, perkiraan jumlah baris untuk masing-masing bagian UNION ALL
adalah 66,8927, yang ketika dijumlahkan sama dengan 133,785, yang kita lihat untuk perkiraan jumlah baris untuk operator gabungan.
Rencana eksekusi aktual untuk kueri gabungan di atas terlihat seperti:
Anda dapat melihat jumlah baris "diperkirakan" vs "aktual". Dalam kasus saya, menambahkan "perkiraan" jumlah baris yang dikembalikan oleh dua operator hash dengan tepat sama dengan jumlah yang ditunjukkan oleh operator gabungan.
Saya akan mencoba untuk mendapatkan hasil dari jejak 2363 dll seperti yang direkomendasikan dalam posting Paul White yang Anda tunjukkan dalam pertanyaan Anda. Sebagai alternatif, Anda dapat mencoba menggunakan OPTION (QUERYTRACEON 9481)
di kueri untuk kembali ke versi 70 CE untuk melihat apakah itu "memperbaiki" masalah.