T-SQL查询性能难题:为什么使用变量会产生影响?

Her*_*ill 12 sql t-sql sql-server query-optimization

当我做出看似无关紧要的变化时,我正在尝试优化复杂的SQL查询并获得截然不同的结果.

例如,运行需要336毫秒:

Declare @InstanceID int set @InstanceID=1;
With myResults as (
    Select 
        Row = Row_Number() Over (Order by sv.LastFirst), 
        ContactID
    From DirectoryContactsByContact(1) sv 
    Join ContainsTable(_s_Contacts, SearchText, 'john') fulltext on (fulltext.[Key]=ContactID)
    Where IsNull(sv.InstanceID,1) = @InstanceID
    and len(sv.LastFirst)>1
) Select * From myResults Where Row between 1 and 20;  
Run Code Online (Sandbox Code Playgroud)

如果我用硬编码的数字替换@InstanceID,则需要超过13秒(13890毫秒)才能运行:

Declare @InstanceID int set @InstanceID=1;
With myResults as (
    Select 
        Row = Row_Number() Over (Order by sv.LastFirst), 
        ContactID
    From DirectoryContactsByContact(1) sv 
    Join ContainsTable(_s_Contacts, SearchText, 'john') fulltext on (fulltext.[Key]=ContactID)
    Where IsNull(sv.InstanceID,1) = 1
    and len(sv.LastFirst)>1
) Select * From myResults Where Row between 1 and 20;  
Run Code Online (Sandbox Code Playgroud)

在其他情况下,我得到完全相反的效果:例如,使用变量@s而不是文字"john"使查询运行速度更慢一个数量级.

有人可以帮我把它绑在一起吗?变量何时使事情变得更快,什么时候变慢?

And*_*mar 2

原因可能是IsNull(sv.InstanceID,1) = @InstanceID对 的某些值非常有选择性@InstanceID,但对其他值则不是很有选择性。例如,可能有数百万行InstanceID = null,因此@InstanceID = 1扫描可能会更快。

但是,如果您显式提供 的值@InstanceID,SQL Server 根据表统计信息知道它是否是选择性的。

首先,确保您的统计数据是最新的:

UPDATE STATISTICS table_or_indexed_view_name 
Run Code Online (Sandbox Code Playgroud)

然后,如果问题仍然出现,请比较两种方法的查询执行计划。然后,您可以使用查询提示强制执行最快的方法。