Ujistěte se, že jste mezi každým testovacím spuštěním vymazali mezipaměť spuštění + dat.
např.
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
Pokud nejprve spustíte s UNION ALL a poté spustíte 2 výběry samostatně, data již budou uložena do mezipaměti, čímž se výkon mnohem zlepší (proto vznikne falešný dojem, že následný přístup je rychlejší, i když nemusí být).
Pokud jste použili UNION, pak to může být pomalejší, protože musí použít DISTINCT, ale UNION ALL to dělat nemusí, takže by to nemělo být jiné.
Aktualizace:
Podívejte se na prováděcí plány a porovnejte je - zjistěte, zda je nějaký rozdíl. Plán provádění můžete zobrazit kliknutím na tlačítko "Zahrnout skutečný plán provádění" v SSMS před spuštěním dotazu
Aktualizace 2:
Na základě uvedených úplných CTE se domnívám, že bych je chtěl optimalizovat – nemyslím si, že problém je ve skutečnosti UNION ALL.
IMHO, nejlepší věc, kterou můžete vyzkoušet, je procházet CTE jeden po druhém a pokusit se optimalizovat každý jednotlivě, takže když je všechny zkombinujete v hlavním dotazu, fungovaly lépe.
např. pro tDictionaryStreets, co takhle zkusit toto:
SELECT DISTINCT
r.KladrItemName AS RegionName,
a.KladrItemName AS AreaName,
c.KladrItemName AS CityName,
sc.KladrItemName AS SubCityName,
s.StreetName
FROM StreetNames s
JOIN tFoundStreets fs ON s.StreetName = fs.KladrItemName
LEFT JOIN tFoundRegions r ON s.RegionName = r.KladrItemName
LEFT JOIN tFoundAreas a ON s.AreaName = a.KladrItemName
LEFT JOIN tFoundCities c ON s.CityName = c.KladrItemName
LEFT JOIN tFoundSubCities sc ON s.SubCityName = scc.KladrItemName
KladrItemName na každé tabulce by měl mít alespoň zapnutý index. Zkuste přepracovat tDictionarySubCities stejným způsobem i se spojeními.