[英]T-SQL ISNULL() Optimization
I have this clause on a join in a stored procedure I inherited: 我有一个关于我继承的存储过程的连接的这个子句:
WHERE a.is_active = 1
AND b.due_date <= ISNULL(@due_date_limit, b.due_date)
How would I re-write this to remove the ISNULL as it's causing severe performance problems? 如何重新编写此文件以删除ISNULL,因为它会导致严重的性能问题?
in this instance, i would have an if statement, checking @due_date_limit 在这个例子中,我会有一个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
AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit
但我不太确定它会快得多。
The most common cause for poor performance with this type of query is because the optimizer can't be sure what the typically value of @due_date_limit will be for most queries. 此类查询导致性能不佳的最常见原因是优化程序无法确定@due_date_limit对大多数查询的典型值。 Often the plan generated and re-used by subsequent executions favor the case where the value is null.
通常,后续执行生成并重新使用的计划支持值为null的情况。
As of SQL 2005 you can guide the optimiser using the "OPTIMIZE FOR" option:- 从SQL 2005开始,您可以使用“OPTIMIZE FOR”选项指导优化器: -
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'))
is there an index on due_Date? due_Date上有索引吗? If not add one and then check the performance.
如果没有添加一个,然后检查性能。 If there already is, then Change to two separate statements
如果已经存在,则更改为两个单独的语句
If @due_date_limit is null
Select [stuff]
From Table
Else
Select [stuff]
From Table
Where b.due_date <= @due_date_limit
But realize that not filtering (when @due_date_limit is null), or filtering using a <= can potentially return a substantial number of records that will eliminate any opportunity to use an index and will require a complete table scan. 但是要意识到不过滤(当@due_date_limit为空时)或使用<=进行过滤可能会返回大量记录,这将消除使用索引的任何机会,并且需要完整的表扫描。 This may be what you are experiencing.
这可能正是您所经历的。
@due_date_limit is a stored procedure variable so it can be factored out from this query all together: @due_date_limit是一个存储过程变量,因此它可以从这个查询中一起分解:
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>
COALESCE(@due_date_limit, b.due_date)
可能有帮助
Since @due_date_limit
is a stored procedure variable, you can just check it for NULL
before the query and set it to a default value if need be, thus eliminating the ISNULL check in the WHERE
clause. 由于
@due_date_limit
是一个存储过程变量,因此您可以在查询之前检查它是否为NULL
,并在需要时将其设置为默认值,从而消除WHERE
子句中的ISNULL检查。
IF (@due_date_limit IS NULL)
BEGIN
SET @due_date_limit = '09/01/2009';
END
and then your WHERE
clause would simply look like this: 然后您的
WHERE
子句将如下所示:
WHERE a.is_active = 1
AND b.due_date <= @due_date_limit
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.