我们有一个 SQL 生成器,它通常为指定的字段发出 SQL 条件语句(为了讨论:我们将标记为myField
)。
如果myField
是 type NVARCHAR
,我们可以将所述字段与字符串进行比较,如下所示myField = 'foo'
:
但是,这不适用于 type 的字段NTEXT
。因此,我们必须使用演员表进行比较: CAST(myField as NVARCHAR(MAX)) = 'foo'
。myField
如果是类型NVARCHAR
或,这实际上会起作用NTEXT
。
在已经是 type的字段上进行上述演员表的性能影响是什么NVARCHAR
?我希望 SQL Server 足够聪明,可以动态识别myField
已经是类型NVARCHAR
(有效地将其CAST
变成无操作)。
如果列的强制转换是完全相同的数据类型和长度,并且搜索谓词是文字,它似乎确实忽略了它或将其视为无操作并在相等时进行索引搜索。
如果列的强制转换是相同的数据类型但长度更大,并且查找谓词是字符串文字,则会导致索引扫描。这显然是要避免的。
如果列的强制转换是相同的数据类型和相同或更大的长度,并且搜索谓词是一个局部变量,它会在执行计划中添加一个计算标量运算符。这会调用
GetRangeThroughConvert
并输出一个范围。此范围用于进行索引查找,看起来非常有效
测试代码
一般来说,这
CAST
会破坏性能,因为它会使任何索引查找的使用无效,正如 Martin Smith 的最后一个示例所示。转换为nvarchar(max)
或转换为不同的长度意味着不同的数据类型:这一切nvarchar
都是无关紧要的。最重要的是,比较右侧的数据类型也很重要。如果它是一个不同长度的局部变量或参数,那么一侧将隐含
CAST
到 2 种数据类型中最宽的一个(请参阅数据类型优先级)。基本上,如果你有一个将军
CAST
,nvarchar(max)
它就会把事情搞砸。ntext
在我全部添加之前,我会考虑修复使用CAST
。转换可能不会显示在查询计划中。请参阅Paul White 的博客文章
请注意,像这样铸造,其中 Datecreated 是日期时间
如果索引存在,则不会破坏 SQL 使用索引的能力,如果它们不存在,可能会导致记录丢失的索引。
类似地,当从
int
totinyint
或bigint
to 进行转换时int
,如果优化器知道转换操作不会更改 2 个可比较数据类型的排序顺序,则转换函数不会阻止 SQL 使用索引。这里有一堆测试,您可以使用 Adventureworks2008R2 运行和查看实际计划