DROP&CREATE FUNCTION改善了性能

时间:2018-08-24 10:15:15

标签: sql sql-server tsql sql-server-2014

我有一个查询,该查询在WHERE子句中使用多语句表值函数,例如:

WHERE value IN (SELECT * FROM dbo.Split('SO',','))

函数的返回值是一个带有单个单元格'SO'的表

我发现没有该功能的查询会更快:

WHERE value = 'SO'
WHERE value IN ('SO')
WHERE value IN (SELECT 'SO')

最终,我在不更改任何代码的情况下删除并创建了该函数,并且查询运行得更快。以前,它不会在一分钟内完成,而现在则需要一秒钟。

当我删除并重新创建该函数时,可能会发生什么变化?

3 个答案:

答案 0 :(得分:3)

这个评论太长了。

SQL Server在第一次调用存储函数和存储过程时会编译查询。优化程序的决定是基于当时的表统计信息和参数。

这被称为 parameter sniffing (我不喜欢该术语,因为决策是基于参数和表统计信息的。)

您的经验表明查询计划不是最理想的-通常这是基于哈希的联接和嵌套循环联接之间的区别。有时,您可以使用索引来解决此问题。

另一个常见的解决方法是强制在编程代码中重新编译一个或多个查询。但是,这会导致重新编译的开销。这样的开销对于运行一分钟的查询来说应该很小,但是如果查询花费的时间少于一秒钟,则开销会更大。

答案 1 :(得分:0)

我将使用CROSS APPLY而不是IN子句:

SELECT t.*
FROM table t CROSS APPLY
    (SELECT * FROM dbo.Split('SO',',') 
    ) tt
WHERE t.value = tt.col;

如果您的string的no_sos很大,则IN子句的性能会很差。

答案 2 :(得分:0)

请尝试使用Tally Tables而不是UDF,让我知道。

declare @mytbl table (Value varchar(100))
insert into @mytbl values('Element01'),('Element04')

DECLARE @Parameter VARCHAR(8000)
    SET @Parameter = ',Element01,'

IF OBJECT_ID('dbo.tally') is not null
drop table dbo.tally

select TOP (select len(@Parameter)) identity(INT,1,1) AS N INTO TALLY FROM Master.dbo.SysColumns sc1,Master.dbo.SysColumns  c2

select * from @mytbl **where Value in (SELECT sUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,n+1)-n-1)
   FROM dbo.Tally
  WHERE N <= LEN(@Parameter)-1
    AND SUBSTRING(@Parameter,N,1) = ','
  )**

谢谢