查询比存储过程慢得多?

时间:2012-11-22 20:05:50

标签: sql-server sql-server-2008 stored-procedures view

我创建了一个查询,它以aprox 2秒执行前100名。如果我创建这个确切查询的存储过程,则需要12-13秒才能运行。

为什么会这样?

  • 元素表计数= 2309015(指定用户ID = 326969)
  • 匹配表计数= 1290(指定用户ID = 498)
  • sites table count = 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 个答案:

答案 0 :(得分:1)

当您创建SP时,它会被编译和存储,当SP具有参数时,您通过该参数过滤结果,优化器不知道您将在执行时传递哪个值,然后将其视为33%选择并由此制定计划。执行查询时,会提供值,优化程序会根据此值创建执行计划。我确定,计划是不同的。

答案 1 :(得分:0)

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

答案 2 :(得分: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
)

答案 3 :(得分:0)

有一个类似的问题here

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