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

Reglar Expression Workbenchコードの使用。

ただし、前述したように、現在コメントアウトされている行がなくても問題なく動作します。

他の提案はありますか?

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)

次に、関数を1回実行した後、レコードを一時テーブルに取得し、一時テーブルを選択します。

于 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

これは、(必要に応じて) の代わりに join を使用して速度を最適化するかnot in、異なるインデックス (おそらく計算列、または一部のカバー インデックス) で最適化できる可能性があります。また、私DISTINCTGROUP BYは多少コードの匂いがありますが、合法である可能性があります。

于 2012-07-25T20:24:36.370 に答える
0

の関数を使用する代わりに、この関数を含めるようにクエリSELECTを変更しました。INSERTそうすれば、後でデータを取得したいときに、すべての行に対して関数を呼び出すことを避けます。

于 2012-07-31T15:50:53.810 に答える