2012-07-25 69 views
1

我想在优化以下查询一些帮助:优化使用函数的SQL Server存储过程?

SELECT DISTINCT TOP (@NumberOfResultsRequested) dbo.FilterRecentSearchesTitles(OriginalSearchTerm) AS SearchTerms 
FROM UserSearches 
WHERE WebsiteID = @WebsiteID 
AND LEN(OriginalSearchTerm) > 20 
--AND dbo.FilterRecentSearchesTitles(OriginalSearchTerm) NOT IN (SELECT KeywordUrl FROM PopularSearchesBaseline WHERE WebsiteID = @WebsiteID) 
GROUP BY OriginalSearchTerm, GeoID 

运行没有被注释掉行罚款。我在UserSearches.OriginalSearchTerm,WebsiteID和PopularSearchesBaseline.KeywordUrl上设置了一个索引,但查询仍然在此处运行缓慢。

- UPDATE - 使用的功能如下:

ALTER FUNCTION [dbo].[FilterRecentSearchesTitles] 
(
    @SearchTerm VARCHAR(512) 
) 

RETURNS VARCHAR(512) 

AS 
BEGIN 
    DECLARE @Ret VARCHAR(512) 

    SET @Ret = dbo.RegexReplace('[0-9]', '', REPLACE(@SearchTerm, '__s', ''), 1, 1) 
    SET @Ret = dbo.RegexReplace('\.', '', @Ret, 1, 1) 
    SET @Ret = dbo.RegexReplace('\s{2,}', ' ', @Ret, 1, 1) 
    SET @Ret = dbo.RegexReplace('\sv\s', ' ', @Ret, 1, 1) 

    RETURN(@Ret) 
END 

使用Reglar Expression Workbench代码。

但是,正如我所提到的 - 没有当前注释的行,它运行良好。

其他建议?

+1

删除该功能。或者向我们展示该功能的功能。如果它对源查询中的每一行都进行数据访问,我认为我们发现了您的问题。考虑将它重写为一个表值函数,然后SQL Server有一些机会来优化它。 – 2012-07-25 19:38:47

回答

0

代替使用SELECT上的函数,我修改了INSERT查询以包含此函数。这样,当我稍后想要检索数据时,我避免为每一行调用函数。

1

我猜测dbo.FilterRecentSearchesTitles(OriginalSearchTerm)是一个函数。我的建议是查看将其重写为table valued function,以便返回可以加入的表格。

否则,你正在为你试图返回的每一行调用该函数,这会导致你的问题。

如果您不能重写功能,那么为什么不创建一个存储过程,将只执行一次,与此类似:

SELECT DISTINCT TOP (@NumberOfResultsRequested) dbo.FilterRecentSearchesTitles(OriginalSearchTerm) AS SearchTerms 
INTO #temp 
WHERE WebsiteID = @WebsiteID 


SELECT * 
FROM #temp 
WHERE SearchTerms NOT IN (SELECT KeywordUrl 
          FROM PopularSearchesBaseline 
          WHERE WebsiteID = @WebsiteID) 

然后你得到你的记录到一个临时表一旦执行功能后然后在临时表上选择。

+0

根据您对每个函数调用的函数的建议,我修改了我的行插入以包含此函数,并将内容添加到新列。这样,我可以避免在SELECT后面的每一行都做这件事。 +1让我走上更好的轨道。 – ElHaix 2012-07-31 15:49:11

1

我可能会尝试在这种情况下,使用persisted computed column

ALTER TABLE UserSearches ADD FilteredOriginalSearchTerm AS dbo.FilterRecentSearchesTitles(OriginalSearchTerm) PERSISTED 

你可能会添加WITH SCHEMABINDING到你的函数(和REGEXREPLACE功能),像这样:

ALTER FUNCTION [dbo].[FilterRecentSearchesTitles] 
(
    @SearchTerm VARCHAR(512) 
) 

RETURNS VARCHAR(512) 

WITH SCHEMABINDING -- You will need this so the function is considered deterministic 

AS 
BEGIN 
    DECLARE @Ret VARCHAR(512) 

    SET @Ret = dbo.RegexReplace('[0-9]', '', REPLACE(@SearchTerm, '__s', ''), 1, 1) 
    SET @Ret = dbo.RegexReplace('\.', '', @Ret, 1, 1) 
    SET @Ret = dbo.RegexReplace('\s{2,}', ' ', @Ret, 1, 1) 
    SET @Ret = dbo.RegexReplace('\sv\s', ' ', @Ret, 1, 1) 

    RETURN(@Ret) 
END 

这使得您的查询看起来像这样:

SELECT DISTINCT TOP (@NumberOfResultsRequested) FilteredOriginalSearchTerm AS SearchTerms 
FROM UserSearches 
WHERE WebsiteID = @WebsiteID 
AND LEN(OriginalSearchTerm) > 20 
AND FilteredOriginalSearchTerm NOT IN (SELECT KeywordUrl FROM PopularSearchesBaseline WHERE WebsiteID = @WebsiteID) 
GROUP BY OriginalSearchTerm, GeoID 

哪些可能会b e通过连接代替not in,或者可能有不同的索引(可能在计算列上,或者一些覆盖索引)来优化速度(如果有必要)。另外,DISTINCTGROUP BY对我来说有点代码味,但它可能是合法的。

+0

是的,你说的是DISTINCT和GROUP BY ...它们只是不同迭代的工件。感谢您的建议。 – ElHaix 2012-07-25 20:40:23