У нас есть генератор SQL, который генерирует условные операторы SQL в общем случае для указанных полей (которые для обсуждения: мы будем обозначать как myField
).
Если myField
имеет тип NVARCHAR
, мы можем сделать сравнение указанного поля со строкой , как так: myField = 'foo'
.
Однако это не работает для полей типа NTEXT
. Таким образом, мы должны сделать сравнение с броском: CAST(myField as NVARCHAR(MAX)) = 'foo'
. Это на самом деле будет работать, если myField
имеет тип NVARCHAR
или NTEXT
.
Какова производительность при выполнении вышеупомянутого приведения на поле, которое уже имеет тип NVARCHAR
? Я надеюсь, что SQL Server достаточно умен, чтобы динамически распознавать, что myField
уже имеет тип NVARCHAR
(эффективно превращая его CAST
в неоперативный).
источник
Ответы:
Если приведение столбца к точно такому же типу данных и длине, а предикат поиска является литералом, он действительно, кажется, игнорирует его или рассматривает как неактивный и выполняет поиск индекса на равенство.
Если приведение столбца к тому же типу данных, но большей длины, и предикат поиска является строковым литералом, это вызывает сканирование индекса. Этого, очевидно, следует избегать.
Если приведение столбца к тому же типу данных и той же или большей длине и предикат поиска является локальной переменной, это добавляет скалярный оператор вычисления в план выполнения. Это вызывает
GetRangeThroughConvert
и выводит диапазон.Этот диапазон используется для поиска по индексу и кажется довольно эффективным
Код тестирования
источник
В целом, производительность
CAST
убьет, потому что она делает недействительным любое использование поиска индекса, как показывает последний пример Мартина Смита. Приведение кnvarchar(max)
или к другой длине означает другой тип данных: факт, что всеnvarchar
это не имеет значения.Кроме того, тип данных правой части сравнения также имеет значение. Если это локальная переменная или параметр другой длины, то одна сторона будет неявно указана
CAST
для самого широкого из двух типов данных (см. Приоритет типа данных ).По сути, если у вас есть общие
CAST
дляnvarchar(max)
него, это запутает вещи. Я хотел бы рассмотреть вопрос об использовании,ntext
прежде чем я добавилCAST
все снова.Конверсия может не отображаться в плане запроса. Смотрите статью в блоге Пола Уайта
источник
Просто примечание, Кастинг как этот, где Datecreated является datetime
Не нарушает способность SQL использовать индексы, если индексы существуют, и если они не существуют, может привести к регистрации отсутствующего индекса.
Аналогично, при приведении
int
кtinyint
илиbigint
иint
т. Д. Функция приведения не останавливает использование SQL индексами, ЕСЛИ оптимизатор знает, что операция приведения не меняет порядок сортировки 2 сопоставимых типов данных.Вот несколько тестов, которые вы можете запустить и просмотреть фактический план, используя Adventureworks2008R2.
источник