【问题标题】:SQL Server Function Efficiency If ExistsSQL Server 函数效率(如果存在)
【发布时间】:2015-10-15 05:51:36
【问题描述】:

我有以下函数返回一点:

Declare @Ret bit
SET @Ret = 0
IF EXISTS ( Select * from tblExclusion where StatusID = 1 and AccountID = @AccountID )
Begin
SET @Ret = 1
End

Return @Ret

现在,表中的同一个 AccountID 可以有多个条目,或者根本没有,但只有一个条目将永远具有“1”状态(如果存在)。

老实说,我对 SQL 不是很了解,但调用该函数时似乎需要很长时间才能返回。我想知道是否有更有效的方式来编写上述内容。

提前致谢。

【问题讨论】:

  • 查询没有问题。如果你索引 StatusID 和 AccountID 它应该非常快
  • 这是一个非常简单的查询,如果它执行缓慢,也许您应该评估表上的现有索引,或者让 DBA 评估是否可以添加。
  • 感谢您的意见,我将研究你们提到的索引方面。

标签: sql performance sql-server-2008 function ssms


【解决方案1】:

索引可能是必要的,查看sample execution plan 将揭示哪些索引会改进。

如果您要将查询修改为:

Declare @Ret bit
SET @Ret = 0
IF EXISTS ( Select 1 from tblExclusion where StatusID = 1 and AccountID = @AccountID )
Begin
SET @Ret = 1
End

Return @Ret

NONCLUSTERED INDEX 的格式为:

USE [DatabaseName]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[tblExclusion] ([StatusID],[AccountID])
<optional, INCLUDE ([columns within the select,]) >
GO

索引的类型和创建方法:Create Index

【讨论】:

    【解决方案2】:

    如果需要很长时间才能运行,那么我会怀疑“AccountID”列上没有索引。在该列上添加索引可能会显着提高性能。但是,在不知道如何定义 tblExclusion 的情况下,无法确定这个答案。此外,假设有大量不同 StatusID 的条目,向 StatusID 添加索引也会有所帮助。

    另外,由于您只需要测试记录的存在,您不需要选择 tblExclusion 中的每一列。您可以将“*”更改为“1”或其他内容,但这不会显着提高性能。

    【讨论】:

    • 选择部分是我认为我有最多问题的部分,感谢您提到索引部分。我会研究这两点。
    • 我不认为改变 * 对 Exists 有任何影响
    • @jazza1000 - 它没有。请参阅我对 SmartDev 的回答的 cmets,包括文档链接。
    【解决方案3】:

    试试这个表格

    Declare @Ret bitSET @Ret = 0
    IF EXISTS ( Select top 1 * from tblExclusion(nolock) where StatusID = 1 and AccountID = @AccountID )
    Begin
    SET @Ret = 1
    End
    
    Return @Ret
    

    记住索引和维护会使这项工作变慢。

    【讨论】:

    • 感谢实现这个改进了执行时间。
    • 该表上有哪些索引?
    【解决方案4】:

    我建议使用select top 1 1 from 而不是select * from,如下所示:

    Declare @Ret bit
    SET @Ret = 0
    IF EXISTS (Select top 1 1 from tblExclusion where StatusID = 1 and AccountID = @AccountID)
    SET @Ret = 1
    
    Return @Ret
    

    这样您就可以避免获取不必要的、可能是大数据的数据。

    【讨论】:

    • 为什么这个神话必须延续?优化器足够聪明,可以意识到它不需要检索任何实际数据来满足EXISTS(SELECT * 重新签入 - 我想说 SQL Server 6.5?也许是 7。当然,当前支持的 SQL Server 版本都不会“获得不需要的并且可能是大数据”
    • 参见例如Subqueries with EXISTS: "子查询实际上并没有产生任何数据"
    猜你喜欢
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    • 2014-01-25
    相关资源
    最近更新 更多