2008-09-18 1 views
1

Я видел, как некоторые люди использовали EXISTS (SELECT 1 FROM ...) вместо EXISTS (SELECT id FROM ...) в качестве оптимизации - вместо того, чтобы искать и возвращать значение, SQL Server может просто вернуть литерал, который он дал.SQL Server: ВЫБРАТЬ буквальное значение быстрее, чем SELECTing?

Действительно ли SELECT(1) всегда быстрее? Будет ли выбор значения из таблицы требовать работу, которую избегал бы выбор литерала?

ответ

6

Ради Бога, я обновлю этот вопрос тем же самым ответом, что и этот (Subquery using Exists 1 or Exists *), так как (в настоящее время) неправильный ответ отмечен как принятый. Обратите внимание, что стандарт SQL фактически говорит, что EXISTS через * идентичен константе.

No. Это было покрыто bazillion раз. SQL Server является интеллектуальным и знает, что он используется для EXISTS и возвращает NO DATA в систему.

Quoth Microsoft: http://technet.microsoft.com/en-us/library/ms189259.aspx?ppud=4

Список выбора подзапроса введенного СУЩЕСТВУЕТ почти всегда состоит из звездочки (*). Существует нет причины перечислять имена столбцов, потому что вы просто проверяете, существуют ли строки, которые соответствуют условиям, указанным в подзапросе .

Кроме того, не верьте мне? Попробуйте выполнить следующие задачи:

SELECT whatever 
    FROM yourtable 
WHERE EXISTS(SELECT 1/0 
       FROM someothertable 
       WHERE a_valid_clause) 

Если это действительно что-то делает с SELECT-списком, это приведет к ошибке div на нуль. Это не так.

EDIT: Обратите внимание, что SQL-стандарт фактически говорит об этом.

ANSI SQL 1992 Standard, стр 191 http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

 3) Case: 

     a) If the <select list> "*" is simply contained in a <subquery> that is immediately contained in an <exists predicate>, then the <select list> is equivalent to a <value expression> that is an arbitrary <literal>. 
+0

спасибо за последующее наблюдение. Принятый ответ изменен. – TSomKes 2010-12-03 17:09:43

1

Да, потому что, когда вы выбираете литерал, ему не нужно читать с диска (или даже из кеша).

+2

Это неправильно, см .: http://stackoverflow.com/questions/1597442/subquery-using-exists-1-or-exists/ – 2009-10-21 18:24:23

1

не имеет значения, что вы выбираете в условии exist. большинство людей действительно выбирают *, тогда сервер sql автоматически выбирает лучший индекс

4

Когда вы используете SELECT 1, вы ясно показываете (тому, кто читает ваш код позже), что вы испытываете, существует ли запись. Даже если нет увеличения производительности (что должно быть обсуждено), наблюдается улучшение читаемости кода и его ремонтопригодности.

+0

Это хороший момент. Немного не по теме, но я согласен с этой идеей. – TSomKes 2008-09-19 03:19:01

-1

Выбрать 1 следует использовать лучше всего в вашем примере. Select * получает все метаданные, связанные с объектами перед запуском, которые рекламируют служебные данные во время усложнения запроса. Хотя вы не видите различий при запуске обоих типов запросов в своем плане выполнения.

8

В SQL Server не имеет значения, используете ли вы SELECT 1 или SELECT * в пределах EXISTS. Вы фактически не возвращаете содержимое строк, но это скорее набор, определенный в предложении WHERE, не является пустым. Попробуйте выполнить запрос бок о бок с SET STATISTICS IO ON, и вы можете доказать, что подходы эквивалентны. Лично я предпочитаю SELECT * в пределах EXISTS.

+0

Согласен. Я просто нахожу WHERE EXISTS (SELECT * FROM ...) более читаемым. Это более интуитивно понятно, что вы просто проверяете, что запись существует, и больше ничего. WHERE EXISTS (SELECT 1 FROM ...) просто кажется неестественным. Разумеется, все субъективное мнение. – njr101 2008-09-22 10:20:05

1

Как заметил кто-то, сервер sql игнорирует список выбора столбцов в EXISTS, поэтому это не имеет значения. Я лично предпочитаю использовать «SELECT null ...», чтобы указать, что это значение вообще не используется.

1

Если посмотреть на план выполнения для

select COUNT(1) from master..spt_values 

и посмотреть на агрегате потока, вы увидите, что он рассчитывает

Scalar Operator(Count(*)) 

Так 1 фактически преобразуются в *

Однако я прочитал где-то в серии «Внутри SQL Server» книги, которые * могут понести очень небольшие накладные расходы для проверки прав доступа столбцов. К сожалению, книга не стала более подробно, чем я помню.

Смежные вопросы