我有一个存储过程非常慢。我运行了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
如果没有创建索引或类似表格的话,是否可以重写以获得更好的性能?
答案 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