我创建了一个查询,它以aprox 2秒执行前100名。如果我创建这个确切查询的存储过程,则需要12-13秒才能运行。
为什么会这样?
码
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
答案 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