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

这里有一个类似的问题

问题是存储过程声明SET ANSI_NULLS OFF

于 2012-11-22T20:27:58.437 回答
0

没有代码,我只能猜测。编写示例查询时,首先有一个常量 where 子句,其次是一个缓存。存储过程没有机会根据 where 子句中的常量缓存或优化查询计划。

于 2012-11-22T20:08:06.123 回答
0

我可以建议两种尝​​试的方法

第一个,这样写​​你的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

二、使用内联表函数

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 回答