1

我需要一些帮助来优化以下查询:

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

使用正则表达式工作台代码。

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

还有其他建议吗?

4

3 回答 3

1

我猜这dbo.FilterRecentSearchesTitles(OriginalSearchTerm)是一个函数。我的建议是查看将其重写为表值函数,以便您可以返回一个可以连接的表。

否则,您将为尝试返回的每一行调用该函数,这将导致您的问题。

如果你不能重写函数,那么为什么不创建一个只执行一次的存储过程,类似于这样:

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)

然后在执行一次函数后将记录放入临时表中,然后在临时表上进行选择。

于 2012-07-25T19:38:44.053 回答
1

在这种情况下,我可能会尝试使用持久计算列:

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,或者不同的索引(可能在计算列或某些覆盖索引上)来优化速度(如有必要)。此外,DISTINCTaGROUP BY对我来说有点代码味道,但它可能是合法的。

于 2012-07-25T20:24:36.370 回答
0

我没有使用 on 函数SELECT,而是修改了INSERT查询以包含此函数。这样,当我以后想要检索数据时,我就避免为每一行调用该函数。

于 2012-07-31T15:50:53.810 回答