Официальный источник, который <> и! = Идентичен по производительности в SQL Server

74

Рассмотрите этот ответ на SO, который убеждает спрашивающего об <>операторе:

<>это ... так же, как !=.

Но затем комментатор трубит и говорит:

Это правда, что они функционально одинаковы. Однако то, как их использует оптимизатор SQL, сильно отличается. = /! = просто оцениваются как истина / ложь, тогда как <> означает, что движок должен посмотреть и посмотреть, больше или меньше это значение, что означает увеличение производительности. Просто нужно учитывать при написании запросов, которые могут быть дорогими.

Я уверен, что это неверно, но чтобы обратиться к потенциальным скептикам, мне интересно, может ли кто-нибудь предоставить авторитетный или канонический источник, чтобы доказать, что эти операторы не просто функционально одинаковы, но идентичны во всех аспектах?

ErikE
источник

Ответы:

144

Во время синтаксического анализа SQL Server вызывает, sqllang!DecodeCompOpчтобы определить тип оператора сравнения:

Стек вызовов

Это происходит задолго до того, как в оптимизатор вмешивается что-либо.

Из операторов сравнения (Transact-SQL)

Операторы сравнения и значения

Отслеживая код с использованием отладчика и открытых символов *, sqllang!DecodeCompOpвозвращает значение в регистре eax** следующим образом:

╔════╦══════╗
║ Op ║ Code ║
╠════╬══════╣
║ <  ║    1 ║
║ =  ║    2 ║
║ <= ║    3 ║
║ !> ║    3 ║
║ >  ║    4 ║
║ <> ║    5 ║
║ != ║    5 ║
║ >= ║    6 ║
║ !< ║    6 ║
╚════╩══════╝

!=и <>оба возвращают 5, поэтому неразличимы во всех последующих операциях (включая компиляцию и оптимизацию).


Хотя это и является вторичным по отношению к вышеупомянутому пункту, также возможно (например, с использованием недокументированного флага трассировки 8605) посмотреть на логическое дерево, переданное оптимизатору, чтобы подтвердить, что и то, !=и другое <>сопоставлено ScaOp_Comp x_cmpNe(не равно сравнение скалярных операторов).

Например:

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID != 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID <> 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

оба производят:

LogOp_Project QCOL: [P] .ProductID
    LogOp_Select
        LogOp_Get TBL: производство.Продукт (псевдоним TBL: P)
        ScaOp_Comp x_cmpNe
            ScaOp_Identifier QCOL: [P] .ProductID
            ScaOp_Const TI (int, ML = 4) XVAR (int, не принадлежит, Value = 4)
    AncOp_PrjList 

Сноски

* Я использую WinDbg ; другие отладчики доступны. Публичные символы доступны через обычный сервер символов Microsoft. Дополнительные сведения см. В разделах «Углубление изучения SQL Server с использованием мини-дампов » консультативной группы по работе с клиентами SQL Server и «Отладка SQL Server с помощью WinDbg» - введение Клауса Ашенбреннера.

** Использование EAX в 32-битных производных Intel для возвращаемых значений из функции является распространенным явлением. Конечно, Win32 ABI делает это таким образом, и я почти уверен, что он унаследовал эту практику от прежних времен MS-DOS, где AX использовался для той же цели - Майкл Кьёрлинг

Пол Уайт
источник
58

Я работаю в Microsoft по поддержке SQL и спросил у Джека Ли, старшего инженера по эскалации и эксперта по вопросам производительности SQL Server: «Относится ли SQL! = К другому, чем <>?» и он сказал: «Они одинаковы».

stacylaray
источник
8

Я думаю, что следующее доказывает, что <>не делает 2 сравнения.

  1. Стандарт SQL 92 определяет <>оператор как не равный ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Технически, !=это расширение стандарта (хотя я не могу думать ни о какой СУБД, которая его не реализует).
  2. Если SQLServer обрабатывается <>как 2 оператора, а не как один, он будет делать то же самое, ><что фактически является синтаксической ошибкой.
a1ex07
источник
1

Это неверно, Books Online (BOL) говорит, что они функционально одинаковы:

! = (Не равно) (Transact-SQL)

И если вы посмотрите на план выполнения, где !=используется, в разделе Предикат, он изменится != на <>.

Райан Купер
источник
2
Проблема в том, что язык «функционально такой же» уже принят в ссылочном комментарии, но делает дополнительное различие в производительности, несмотря на то, что вы и мои знания, что «функционально то же самое», включает в себя то, как он на самом деле работает, и любые характеристики производительности. Что делать, если кто-то собирается доказать это сверх всякого решительного скептицизма?
ErikE