Головоломка оптимізатора запитів SQL-сервера 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), є крайнім способом вирішення, але в деяких випадках - єдиний спосіб змусити оптимізатор повністю розділити дві частини запиту так, як вам потрібно.