Выберите, где порядок оценки предложения

В Sql Server 2005, когда у меня есть несколько параметров, есть ли у меня гарантия того, что порядок оценки будет всегда слева направо?

Используя пример:

select a from table where c=1 and d=2

В этом запросе, если условие «c = 1» не выполняется, условие «d = 2» никогда не будет оцениваться?

PS- «c» — столбец с целочисленным индексом, d — большой varchar и неиндексируемый столбец, для которого требуется полное сканирование таблицы.

update Я пытался избежать выполнения двух запросов или условных операторов, мне просто нужно что-то вроде: если "c условие" не выполняется, есть способ избежать выполнения тяжелого "d условия", так как это не нужно в мое дело.


person t3mujin    schedule 27.01.2009    source источник


Ответы (7)


Нет никаких гарантий для порядка оценки. Оптимизатор попытается найти наиболее эффективный способ выполнения запроса, используя доступную информацию.

В вашем случае, поскольку c индексируется, а d нет, оптимизатор должен просмотреть индекс, чтобы найти все строки, соответствующие предикату c, а затем извлечь эти строки из данных таблицы, чтобы оценить предикат d.

Однако, если он определяет, что индекс для c не очень избирательный (хотя в вашем примере это не так, столбец гендера редко индексируется с пользой), он все равно может принять решение о сканировании таблицы.

Чтобы определить порядок выполнения, вы должны получить план объяснения для вашего запроса. Однако имейте в виду, что этот план может измениться в зависимости от того, что оптимизатор считает лучшим запросом прямо сейчас.

person kdgregory    schedule 27.01.2009
comment
Хотя это и не было явным в моем вопросе, я также имел в виду поиск неиндексированного столбца среди найденных элементов в индексированном столбце. В моем случае это полностью соответствует моим потребностям, потому что сначала запрос индексированного столбца оставит лишь небольшое количество записей для фильтрации, что не является проблемой. - person t3mujin; 27.01.2009
comment
Просто запомните мое последнее предложение: оптимизатор может выбрать другой план запроса для каждого выполнения. Есть способы закрепить планы, а также указать подсказки оптимизатору; Я не знаком с тем, как они работают в MS-SQL. - person kdgregory; 27.01.2009
comment
Смысл использования декларативного языка в том, что система определяет для вас наилучший план выполнения. Оптимизаторы, как правило, хорошо справляются с такими вещами с текущей статистикой; что-то, называемое вихрями, теоретически может работать вообще без статистики, но это недавнее изобретение, и его может не быть в MS-SQL. - person SquareCog; 28.01.2009
comment
Можем ли мы утверждать, что индексированные столбцы ВСЕГДА будут оцениваться первыми по сравнению с неиндексированными столбцами? - person anar khalilov; 27.05.2014
comment
@ АнарХалилов - нет. Разные базы данных будут применять разные правила оптимизации. Oracle, например, может использовать статистику на уровне столбца, чтобы определить, когда индекс будет достаточно избирательным. - person kdgregory; 28.05.2014
comment
@kdgregory На самом деле я имел в виду SQL Server, но забыл упомянуть об этом. - person anar khalilov; 28.05.2014

SQL Server создаст оптимизированный план для каждого выполняемого оператора. Вам не нужно заказывать предложение where, чтобы получить это преимущество. Единственная гарантия, которую вы имеете, заключается в том, что она будет запускать операторы в следующем порядке:

SELECT A FROM B WHERE C
SELECT D FROM E WHERE F

запустит первую строку перед второй.

person Orion Adrian    schedule 27.01.2009
comment
Другими словами: НЕТ. SQL Server переупорядочит ваши условия where, как он считает, самым быстрым способом. Если ваши условия where имеют побочные эффекты (возможно, через вызовы функций udf), это может вызвать проблемы. - person Joel Coehoorn; 27.01.2009
comment
Размещение UDF в предложениях WHERE может быть катастрофически медленным. Нам более или менее пришлось объявить их вне закона, производительность была настолько плохой. - person Joe; 27.01.2009
comment
Орион, вообще-то нет.. это тоже не гарантировано - person SquareCog; 28.01.2009
comment
и @SquareCog! Даже если гарантировано, вряд ли будет какая-либо разница в производительности. - person IsmailS; 10.09.2010

Одним из способов управления порядком вычисления является выражение CASE.

[Редактировать]

Популярное мнение, которое я пытался выразить, было следующим:

Вы не можете зависеть от порядка оценки выражения для таких вещей, как «ГДЕ ИЛИ», поскольку оптимизатор может выбрать план, который оценивает второй предикат перед первым. Но порядок оценки выражений в операторе CASE фиксирован, поэтому вы можете полагаться на детерминированную оценку короткого замыкания оператора CASE.

Это становится немного сложнее, как описано на сайте ниже:

http://blogs.msdn.com/b/bartd/archive/2011/03/03/don-t-depend-on-expression-short-circuiting-in-t-sql-not-even-with-case.aspx

person Ric Tokyo    schedule 27.01.2009
comment
Связанная страница удалена. - person Conrad; 09.09.2014

Вы можете просмотреть план выполнения запроса и определить, что он на самом деле пытается сделать. Я думаю, что механизм запросов SQL Server должен выполнять этот тип сканирования и разумно преобразовывать его в операции. Например, если вы сделаете «дорогую операцию И ложь», она быстро будет оценена как ложь.

Из того, что я узнал, то, что вы печатаете, отличается (и может быть) от того, что на самом деле выполняется. Вы просто сообщаете серверу, каких результатов вы ожидаете. То, как он получает ответ, не коррелирует слева направо с кодом, который вы предоставляете.

person Mark Canlas    schedule 27.01.2009

Если вы хотите убедиться, вы можете проверить план выполнения запроса. План выполнения, который строит/оптимизирует MSSQL, достаточно умен, чтобы проверять индексированный столбец перед столбцом varchar.

person cgreeno    schedule 27.01.2009

Короткое замыкание выполняется, когда условие, на которое мы ссылаемся, включает только литералы или константы. Так, например, скажем, у нас есть таблица TableA, в которой есть столбец num со всеми положительными числами от 1 до 10, а затем, если я напишу этот запрос.

Выберите число из таблицы A, ГДЕ TableA.num ‹ 0 AND 1/0 = 10.

Это приведет к ошибке.

Достаточно ли умен компилятор, чтобы определить, что мое второе предложение состоит из констант, поэтому он должен оценить это перед оценкой предложения, которое требует любого сканирования из таблицы или индекса?

person Nitin Midha    schedule 04.11.2009

Оптимизатор запросов MS SQL Server делает короткое замыкание, да. Гарантировано.

Запустите это:

select 1 where 1 = 0 and 1 / 0 = 10

Он будет работать нормально и без ошибок, даже если вы делите на ноль, потому что оптимизатор запросов укоротит оценку предложения where. Это имеет значение для любого предложения where, где вы используете «и», а одна из частей и является константой.

person Robert C. Barth    schedule 27.01.2009
comment
Извините, я не верю, что вы правы. Я думаю, что @kdgregory прав в том, что здесь нет никаких гарантий. Оптимизатор запросов решит, что лучше. - person Gary Brunton; 07.11.2013
comment
Это определенно не гарантируется - прямо сейчас я имею дело с такой ситуацией, когда я хочу, чтобы короткое замыкание не оценивало выражения, когда истинное значение уже известно (с учетом обычного приоритета оператора), но этого не происходит. - person Conrad; 09.09.2014
comment
Эти две части предложения where являются тривиальными выражениями, поэтому оптимизатор запросов не беспокоится о том, чтобы изменить их порядок. Попробуйте вместо этого: выберите 1, где существует (выберите «Любые строки?» из dbo.LargishTable) и 1/0 = 10. Существуют некоторые пороговые значения, основанные на способе, которым оптимизатор запросов создает планы выполнения, определяющие порядок оценки. - person Davos; 16.12.2015