Головоломка оптимизатора запросов SQL Server 2008 R2
У нас есть две таблицы, каждая из которых содержит 9 миллионов строк. 70 000 строк разные, остальные одинаковые.
Это быстро, 13 секунд,
select * from bigtable1
except select * from similar_bigtable2
Это сортирует вывод и также быстро, 13 секунд,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Пока это невероятно медленно
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
И даже «трюк», который я иногда использую, чтобы намекнуть SQL Server, что ему необходимо предварительно рассчитать определенную часть запроса, прежде чем он будет выполнен, не работает и также приводит к медленному запросу:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Глядя на планы запросов, найти причину несложно:
SQL Server помещает два сорта по 9 миллионов строк перед хэш-соответствием, в то время как я бы предпочел, чтобы после хеш-соответствия было добавлено только один вид из 70 000 строк .
Итак, вопрос: как я могу поручить оптимизатору запросов сделать это?
EXCEPT
(например OUTER JOIN
)? Я понимаю, что синтаксис менее удобен, но вы можете лучше использовать подсказки индексации / объединения (или вам это может не понадобиться). Альтернатива, которую вы используете сейчас (сначала добавьте в таблицу #temp), является последним средством, но в некоторых случаях это единственный способ заставить оптимизатор полностью разделить две части запроса так, как вам нужно.