我想在优化以下查询方面提供一些帮助:
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上设置了一个索引,但是该行中的查询仍然运行缓慢。
- 更新 - 使用的功能如下:
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代码。
然而,正如我所提到的 - 如果没有当前注释掉的行,它运行正常。
还有其他建议吗?
答案 0 :(得分: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)
然后在执行一次函数后将记录放入临时表中,然后在临时表上选择。
答案 1 :(得分: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
可能使用连接而不是not in
来优化速度(如果需要),或者可能是不同的索引(可能在计算列或某些覆盖索引上)。另外,带有DISTINCT
的{{1}}对我来说有点代码味道,但它可能是合法的。
答案 2 :(得分:0)
我没有使用SELECT
上的函数,而是修改了INSERT
查询以包含此函数。这样,当我以后想要检索数据时,我避免为每一行调用该函数。