AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 9832
Accepted
Ryan Delucchi
Ryan Delucchi
Asked: 2010-07-02 15:11:16 +0800 CST2010-07-02 15:11:16 +0800 CST 2010-07-02 15:11:16 +0800 CST

在 T-SQL 中使用 CAST 会影响性能

  • 772

我们有一个 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变成无操作)。

sql-server performance
  • 3 3 个回答
  • 20961 Views

3 个回答

  • Voted
  1. Best Answer
    Martin Smith
    2010-07-02T15:25:13+08:002010-07-02T15:25:13+08:00

    如果列的强制转换是完全相同的数据类型和长度,并且搜索谓词是文字,它似乎确实忽略了它或将其视为无操作并在相等时进行索引搜索。

    Seek Keys[1]: Prefix: [tempdb].[dbo].[#test].name = Scalar Operator(N'rpc')
    

    如果列的强制转换是相同的数据类型但长度更大,并且查找谓词是字符串文字,则会导致索引扫描。这显然是要避免的。

    如果列的强制转换是相同的数据类型和相同或更大的长度,并且搜索谓词是一个局部变量,它会在执行计划中添加一个计算标量运算符。这会调用GetRangeThroughConvert并输出一个范围。

    此范围用于进行索引查找,看起来非常有效

    Seek Keys[1]: 
    Start: [tempdb].[dbo].[#test].name > Scalar Operator([Expr1006]), 
    End: [tempdb].[dbo].[#test].name < Scalar Operator([Expr1007])
    

    测试代码

    SELECT *
     INTO #test
      FROM [master].[dbo].[spt_values]
    
    CREATE NONCLUSTERED INDEX [ixname] ON #test
    (
        [name] ASC
    )
    
    DECLARE @name NVARCHAR(MAX)
    
    SET @name = 'rpc'
    
    SELECT name
    FROM #test
    WHERE CAST(name AS NVARCHAR(35))= @name --Cast the same and local variable
    
    SELECT name
    FROM #test
    WHERE CAST(name AS NVARCHAR(MAX))=@name --Cast to longer and local variable
    
    SELECT name
    FROM #test
    WHERE CAST(name AS NVARCHAR(35))='rpc' --Cast the same and literal
    
    SELECT name
    FROM #test
    WHERE CAST(name AS NVARCHAR(MAX))='rpc' --Cast to longer and literal
    
    • 12
  2. gbn
    2010-07-02T21:25:50+08:002010-07-02T21:25:50+08:00

    一般来说,这CAST会破坏性能,因为它会使任何索引查找的使用无效,正如 Martin Smith 的最后一个示例所示。转换为nvarchar(max)或转换为不同的长度意味着不同的数据类型:这一切nvarchar都是无关紧要的。

    最重要的是,比较右侧的数据类型也很重要。如果它是一个不同长度的局部变量或参数,那么一侧将隐含CAST到 2 种数据类型中最宽的一个(请参阅数据类型优先级)。

    基本上,如果你有一个将军CAST,nvarchar(max)它就会把事情搞砸。ntext在我全部添加之前,我会考虑修复使用CAST。

    转换可能不会显示在查询计划中。请参阅Paul White 的博客文章

    • 6
  3. Doran Mackay
    2014-08-02T02:47:41+08:002014-08-02T02:47:41+08:00

    请注意,像这样铸造,其中 Datecreated 是日期时间

     Cast (Datecreated as date) = cast(@MydatetimeValue as date)
    

    如果索引存在,则不会破坏 SQL 使用索引的能力,如果它们不存在,可能会导致记录丢失的索引。

    类似地,当从inttotinyint或bigintto 进行转换时int,如果优化器知道转换操作不会更改 2 个可比较数据类型的排序顺序,则转换函数不会阻止 SQL 使用索引。

    这里有一堆测试,您可以使用 Adventureworks2008R2 运行和查看实际计划

    select count(*) from Sales.SalesOrderDetail where SalesOrderID = 8 --1
    select top 10 * from Sales.SalesOrderDetail where cast(SalesOrderID as tinyint) = 8  --2
    select top 10 * from Sales.SalesOrderDetail where cast(SalesOrderID as bigint) = 8  --3
    select top 10 SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate  as date) = '19780322' --4
    select top 10 SalesOrderID from Sales.SalesOrderDetail where convert(date,ModifiedDate) = '19780322'  --5
    select top 10 SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate as varchar(20)) = '1978'  --6 -- THIS WILL NOT USE INDEX
    select  SalesOrderID from Sales.SalesOrderDetail where cast(ModifiedDate  as date) between '19780101' and '19780109'  --7
    
    • 4

相关问题

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何在转储中使用使用数据库执行 mysqldump

    • 4 个回答
  • Marko Smith

    在 MySQL Workbench 中,在表的“顶部”插入一个新列?

    • 4 个回答
  • Marko Smith

    SQL Server - 临时表与物理表

    • 3 个回答
  • Marko Smith

    什么时候全表扫描比索引扫描更好?

    • 4 个回答
  • Marko Smith

    收缩数据库和文件有什么区别?

    • 3 个回答
  • Marko Smith

    Sql FILESTREAM 垃圾回收问题

    • 1 个回答
  • Marko Smith

    SQL Server 2008 DBCC 问题

    • 2 个回答
  • Marko Smith

    如何在恢复中停止、脱机和删除 SQL Server 数据库?

    • 2 个回答
  • Marko Smith

    如何将 SQL Server 2000 数据库恢复到 SQL Server 2008 实例?

    • 5 个回答
  • Marko Smith

    在 T-SQL 中使用 CAST 会影响性能

    • 3 个回答
  • Martin Hope
    user481826 如何在转储中使用使用数据库执行 mysqldump 2010-10-29 16:08:59 +0800 CST
  • Martin Hope
    Will A SQL Server - 临时表与物理表 2010-07-05 08:46:10 +0800 CST
  • Martin Hope
    NibblyPig SQL 2008 中的表分区 - 为什么? 2010-06-30 00:59:23 +0800 CST
  • Martin Hope
    Gnomo 解释执行计划 2010-09-10 10:31:11 +0800 CST
  • Martin Hope
    ahsan 什么时候全表扫描比索引扫描更好? 2010-12-10 10:16:54 +0800 CST
  • Martin Hope
    Tom DeMille 我应该定期缩小我的数据库或至少我的日志文件吗? 2010-04-24 08:19:19 +0800 CST
  • Martin Hope
    Jango 收缩数据库和文件有什么区别? 2010-08-24 10:25:42 +0800 CST
  • Martin Hope
    CrapHands 如何在恢复中停止、脱机和删除 SQL Server 数据库? 2010-12-18 07:12:36 +0800 CST
  • Martin Hope
    Ryan Delucchi 在 T-SQL 中使用 CAST 会影响性能 2010-07-02 15:11:16 +0800 CST
  • Martin Hope
    Manjot SQL 2005:我们能否确定重建索引维护作业可以使数据库日志文件增长多少? 2010-08-12 18:40:44 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve