1

トップ100で約2秒で実行されるクエリを作成しました。この正確なクエリのストアドプロシージャを作成すると、実行に12〜13秒かかります。

なぜでしょうか?

  • 要素テーブル数 = 2309015 (指定されたユーザー ID = 326969)
  • 一致するテーブル数 = 1290 (指定されたユーザー ID = 498)
  • サイト テーブル数 = 71 (指定されたユーザー ID = 9)

コード

 with search (elementid, siteid, title, description, site, link, addeddate)
 as
 (
     select top(@top) 
         elementid,
         elements.siteid, title, elements.description,
         site =
             case sites.description
                 when '' then sites.name
                 when null then sites.name
                 else sites.name + ' (' + sites.description + ')'
             end, 
        elements.link,
        elements.addeddate 
    from elements
        left join sites on elements.siteid = sites.siteid
    where title like @search and sites.userid = @userid
    order by addeddate desc
)
select search.*, isnull(matches.elementid,0) as ismatch 
from search
    left join matches on matches.elementid = search.elementid
4

4 に答える 4

1

SP を作成すると、それはコンパイルされて保存されます。SP にパラメーターがあり、結果をフィルター処理する場合、オプティマイザーは実行時に渡す値がわからないため、33% の選択として扱い、これによって計画を作成します。クエリを実行すると、値が提供され、オプティマイザーはこの値に応じて実行計画を作成します。確かに、計画は異なります。

于 2012-11-22T20:26:50.013 に答える
0

コードがなければ、推測しかできません。サンプル クエリを作成する場合、まず定数 where 句を作成し、次にキャッシュを作成します。ストアド プロシージャは、where 句の定数に基づいてクエリ プランをキャッシュまたは最適化する可能性はありません。

于 2012-11-22T20:08:06.123 に答える
0

試してみる2つの方法を提案できます

まず、sp を次のように記述します。

create procedure sp_search
(
    @top int,
    @search nvarchar(max),
    @userid int
)
as
begin
    declare @p_top int, @p_search nvarchar(max), @p_userid int

    select @p_top = @top, @p_search = @search, @p_userid = @userid

    with search (elementid, siteid, title, description, site, link, addeddate)
    as
    (
        select top(@p_top) 
            elementid,
            elements.siteid, title, elements.description,
            site =
             case sites.description
                 when '' then sites.name
                 when null then sites.name
                 else sites.name + ' (' + sites.description + ')'
             end, 
            elements.link,
            elements.addeddate 
        from elements
            left join sites on elements.siteid = sites.siteid
        where title like @p_search and sites.userid = @p_userid
        order by addeddate desc
    )
    select search.*, isnull(matches.elementid,0) as ismatch 
    from search
        left join matches on matches.elementid = search.elementid
end

2 つ目は、インライン テーブル関数を使用します。

create function sf_search
(
    @top int,
    @search nvarchar(max),
    @userid int
)
returns table
as
return
(
    with search (elementid, siteid, title, description, site, link, addeddate)
    as
    (
        select top(@top) 
            elementid,
            elements.siteid, title, elements.description,
            site =
             case sites.description
                 when '' then sites.name
                 when null then sites.name
                 else sites.name + ' (' + sites.description + ')'
             end, 
            elements.link,
            elements.addeddate 
        from elements
            left join sites on elements.siteid = sites.siteid
        where title like @search and sites.userid = @userid
        order by addeddate desc
    )
    select search.*, isnull(matches.elementid,0) as ismatch 
    from search
        left join matches on matches.elementid = search.elementid
)
于 2012-11-22T20:23:48.463 に答える
0

ここに同様の質問があります

問題はストアド プロシージャ宣言でしたSET ANSI_NULLS OFF

于 2012-11-22T20:27:58.437 に答える