代码之家  ›  专栏  ›  技术社区  ›  Frozenskys

t-sql isnull()优化

  •  6
  • Frozenskys  · 技术社区  · 15 年前

    我在继承的存储过程中的join上有这个子句:

    WHERE a.is_active = 1
    AND b.due_date <= ISNULL(@due_date_limit, b.due_date)
    

    如何重新编写此命令以删除IsNull,因为它会导致严重的性能问题?

    7 回复  |  直到 11 年前
        1
  •  7
  •   Adriaan Stander    15 年前

    在这个例子中,我会有一个if语句,检查@due_date_limit

    IF (@due_date_limit IS NULL)
    BEGIN
        ...
        WHERE   a.is_active = 1 --not required to compare b.due_date <= b.due_date
    END
    ELSE
    BEGIN
        ...
        WHERE   a.is_active = 1
        AND     b.due_date <= @due_date_limit
    END
    
        2
  •  3
  •   AnthonyWJones    15 年前

    这种类型查询性能不佳的最常见原因是,优化器无法确定大多数查询的@due_date_limit通常值是多少。通常,由后续执行生成并重新使用的计划倾向于值为空的情况。

    从SQL 2005起,您可以使用“优化对象”选项指导优化对象:

    WHERE a.is_active = 1
    AND b.due_date <= ISNULL(@due_date_limit, b.due_date)
    OPTION (OPTIMIZE FOR (@due_date_limit = '09/01/2009'))
    
        3
  •  2
  •   Jonas Elfström    15 年前
    AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit
    

    但我不太确定它会更快。

        4
  •  2
  •   Charles Bretana    15 年前

    到期日有索引吗?如果没有,请添加一个,然后检查性能。如果已经存在,则改为两个单独的语句

      If @due_date_limit is null
        Select [stuff]
        From Table
      Else
        Select [stuff]
        From Table  
        Where b.due_date <= @due_date_limit
    

    但请注意,不进行筛选(当@due_date_limit为空时)或使用<=进行筛选可能会返回大量记录,这些记录将消除任何使用索引的机会,并且需要进行完整的表扫描。这可能是你正在经历的。

        5
  •  1
  •   topchef    15 年前

    @“到期日期限制”是一个存储过程变量,因此可以将其从该查询中全部分解出来:

    if (@due_date_limit is NULL) 
       <run query that works when @due_date_limit is NULL>
    else 
       <run query that works when @due_date_limit is NOT NULL>
    
        6
  •  1
  •   manji    15 年前
    COALESCE(@due_date_limit, b.due_date)
    

    可以帮助

        7
  •  0
  •   johntrepreneur    11 年前

    自从 @due_date_limit 是一个存储过程变量,您只需检查它 NULL 在查询之前,如果需要,请将其设置为默认值,从而消除 WHERE 条款。

    IF (@due_date_limit IS NULL)
    BEGIN
        SET @due_date_limit = '09/01/2009';
    END
    

    然后你的 哪里 子句将简单如下:

    WHERE a.is_active = 1
    AND b.due_date <= @due_date_limit