Початковий погляд на плани виконання показує, що вираз 1/0
визначений в операторах Compute Scalar:
Тепер, навіть незважаючи на те, що плани виконання дій починають виконуватися в крайній лівій частині, ітеративно виклику Open
і GetRow
методів дочірніх ітераторів для повернення результатів, SQL Server 2005 і пізніше містить оптимізацію, згідно з якою вирази часто визначаються лише Обчислювальним скаляром, а оцінка відкладається до наступного Операція вимагає результату :
У цьому випадку результат вираження потрібен лише під час збирання рядка для повернення до клієнта (що можна подумати про те, що відбувається у зеленому SELECT
значку). За цією логікою відкладене оцінювання означало б, що вираз ніколи не оцінюється, оскільки жоден план не створює ряд повернення. Щоб трохи попрацювати над точкою, ні кластерний пошук пошуку, ні сканування таблиці не повертають рядка, тому немає рядка для збирання для повернення до клієнта.
Однак існує окрема оптимізація, згідно з якою деякі вирази можуть бути ідентифіковані як константи часу виконання і так оцінені один раз перед початком виконання запиту . У цьому випадку вказівку на цю ситуацію можна знайти в XML-шоу XML (План пошуку кластерних індексів зліва, План сканування таблиці справа):
Про основні механізми та про те, як вони можуть вплинути на ефективність, я писав у цій публікації в блозі . Використовуючи інформацію, надану там, ми можемо змінити перший запит, щоб обидва вирази були оцінені та кешовані перед початком виконання:
select 1/0 * CONVERT(integer, @@DBTS)
from #temp
where id = 1
select 1/0
from #temp2
where id = 1
Тепер перший план також містить посилання на постійний вираз, і обидва запити створюють повідомлення про помилку. XML для першого запиту містить:
Додаткова інформація: Обчислити скаляри, вирази та продуктивність