使用函数优化SQL查询

时间:2014-08-14 12:26:53

标签: sql sql-server sql-server-2008 tsql

我有一个存储过程非常慢。我运行了SP并查看了执行计划,并且能够看到花了这么长时间。

缓慢的部分:

DECLARE
 @id int 
,@date datetime
,@endDate datetime 


SELECT   @id = 3483
        ,@date = DATEADD(DAY, -10, GETDATE())
        ,@endDate = GETDATE()


SET NOCOUNT ON

SELECT   *
        ,prevId = dbo.fnGetPrevId(id)   
FROM    dbo.table WITH(READUNCOMMITTED)

此查询中缓慢的部分是我调用函数dbo.fnGetPrevId的地方。

dbo.fnGetPrevId:

DECLARE  @prevId int

SELECT  TOP 1 @prevId = t2.id 
FROM    dbo.table2 AS t2 WITH(READUNCOMMITTED)

RETURN @prevId

如果没有创建索引或类似表格的话,是否可以重写以获得更好的性能?

4 个答案:

答案 0 :(得分:3)

您可以使用子查询而不是标量值函数。

// ...

,prevId = (
 SELECT  TOP 1 x.id
 FROM    dbo.table AS x WITH(READUNCOMMITTED)
 WHERE 1 = 1)

// ...

在大多数情况下,最好避免使用引用表的标量值函数,因为它们基本上是需要为每一行运行一次的黑盒子,并且无法通过查询计划引擎进行优化。

答案 1 :(得分:1)

首先,您应该将所有功能一起剪切并内联查询。从我看来,这将是相当简单的。或者,如果要保留函数,则使用表值函数。对于两个检查:

http://technet.microsoft.com/en-us/library/ms175156(v=sql.105).aspx

其次,优化你的最佳结果将是建立一个指数(巨大改进)

答案 2 :(得分:0)

首先在表上创建索引(id,id2,id3 ....)`。

这可以解决您的问题。否则,请尝试cross apply

FROM    dbo.table1 AS x WITH(READUNCOMMITTED) cross apply
        (SELECT  TOP 1 x2.id
         FROM    dbo.table2 as x2 WITH(READUNCOMMITTED)
          WHERE x.id= x2.id
            AND x.id2= x2.id2
            AND x.id3= x2.id3
         ORDER BY x.Date DESC
        ) x

答案 3 :(得分:0)

您的UDF正在为其运行的每一行重新编译。要停止它,请将函数设为Table值内联函数,如下所示:

create function dbo.fnFunction:
( list of parameters here)
Returns Table
As
  Return 
   (
    SELECT TOP 1 id
    FROM  dbo.table WITH(READUNCOMMITTED)
    WHERE id= @id
       AND id2= @id2
       ...
   ORDER BY date DESC
  )

这消除了对每一行的重新编译,因为内联表值函数中的SQL包含在它所使用的查询的sql中,并且只存储在整个查询ONCE的缓存计划中,并且只存储一次。要使用结果,您需要像处理表一样处理结果。只需在外部查询中加入,请查看此link