存储过程执行速度慢,该怎么处理

存储过程执行速度慢
今日写存储过程执行查询作业,整体数据量有千万条,代码大概如下:

ALTER  proc [dbo].[zd_lxfl_old0228] 
 @spbh varchar(20)='',
 @s_rq varchar(10)='',
 @e_rq varchar(10)='',
 @danwbh varchar(20)='',

 @cd varchar(100)='',
 @orgid int ,
 @isnlj int,
 @xylb int
as 

begin 
declare @varspbh VARCHAR(20)
declare @vars_rq VARCHAR(10)
declare @vare_rq VARCHAR(10)
declare @vardanwbh VARCHAR(20)
--declare @vart int
declare @varcd VARCHAR(20)
--declare @varghdwbh VARCHAR(100)
declare @varorgid int
declare @varisnlj int
declare @varxylb int
begin
set @varspbh=@spbh;
set @vars_rq=@s_rq;
set @vare_rq=@e_rq;
set @vardanwbh=@danwbh;
--set @vart=@t;
set @varcd=@cd;
--set @varghdwbh=@ghdwbh;
set @varorgid=@orgid;
set @varisnlj=@isnlj;
set @varxylb=@xylb;
end
select row_number() OVER (ORDER BY a.rq,a.djbh ASC) AS id,
a.orgid,
(case when a.lx=0 then a.shl*a.xsshl else 0 end 
+ case when a.lx=1 then a.shl*a.hsje else 0 end
+(case when  @varisnlj=1 then lxbynxse else 0 end)
- case when b.jsje is not null then b.jsje else 0 end
-case when c.jsje IS not null and c.jsje>0 
then round(c.jsje,2) else 0 end) as bcjs,

a.dwbh ,a.annual_TotalSales,

lxbynxse,lxbynxse_contract,

cast(g.credit as varchar)+'~'+cast(g.creditend as varchar) as lxbynxse_credit,
lxbynxseid_contract, h.rate as lxbynxseid_contract_rate,
cast(h.credit as varchar)+'~'+cast(h.creditend as varchar) as lxbynxse_contract_credit,
round (((case when a.lx=0 then a.shl*a.xsshl else 0 end)+(case when a.lx=1 then a.shl*a.hsje else 0 end)+isnull(a.lxbynxse_contract,0)),2) as sale_rebate_contract
-----------a.yesfltj,a.nofltj,-------------------
from  (select   a.orgid,a.spid,a.spbh,a.spmch,a.shpgg,a.dw,a.shpchd,a.xsshl,a.hsje,
a.danwbh,a.dwmch,a.jiyili,a.rq,a.djbh,a.cgfzr,a.dwbh ,a.bm,

case when len(ltrim(rtrim(b.beizhu)))=6 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),6) then 1
when len(ltrim(rtrim(b.beizhu)))=5 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),5) then 1
when len(ltrim(rtrim(b.beizhu)))=4 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),4) then 1
when len(ltrim(rtrim(b.beizhu)))=len(ltrim(rtrim(a.danwbh))) and ltrim(rtrim(b.beizhu))=ltrim(rtrim(a.danwbh)) then 1
else 0
end yesfltj,

gf.credit as lxbynxsecredit,gf.creditend as lxbynxsecreditend,gf.rate as lxbynxserate,gf.id as lxbynxseid1,
sum(case when gf.type=5 and (datediff(day,gf.start_date,a.rq)>=0 and datediff(day,a.rq,gf.end_date)>=0) 
and ((gf.creditend>gf.credit and  e.annual_TotalSales>gf.credit and  e.annual_TotalSales<=gf.creditend) or(gf.creditend=gf.credit and gf.credit<>0 and e.annual_TotalSales>gf.credit) or (gf.creditend=gf.credit and gf.credit=0)) 
then  gf.id else 0 end) as lxbynxseid, 
sum(case when gf.type=5 and (datediff(day,gf.start_date,a.rq)>=0 and datediff(day,a.rq,gf.end_date)>=0) 
and ((gf.creditend>gf.credit and  e.annual_TotalSales>gf.credit and  e.annual_TotalSales<=gf.creditend) or(gf.creditend=gf.credit and gf.credit<>0 and e.annual_TotalSales>gf.credit) or (gf.creditend=gf.credit and gf.credit=0)) 
then  a.hsje * gf.rate else 0 end) as lxbynxse


from dbo.buisnessData_lx a
left join dbo.fl_cg_new_v gf on a.orgid=gf.orgid
and a.spid=gf.spid
and datediff(day,gf.rl_start_date,a.rq)>=0
and datediff(day,a.rq,gf.rl_end_date)>=0
and (gf.type=5)
left join dbo.fl_lx_v b on  (a.spid=b.spid and a.orgid=b.orgid and  DATEDIFF(DAY,b.ksrq,a.rq)>=0 and DATEDIFF(DAY,a.rq,b.zzrq)>=0)

where not exists(select spid,beizhu 
 from dbo.fl_lx 
 where spid=a.spid and ltrim(rtrim(substring(beizhu,charindex('?',beizhu)+1,20)))=
case when len(ltrim(rtrim(substring(beizhu,charindex('?',beizhu)+1,20))))=6 then left(ltrim(rtrim(a.danwbh)),6)

 else  ltrim(rtrim(a.danwbh)) end and charindex('?',beizhu)>0)
group by a.djbh,a.rq ,a.xsshl,a.bm,b.beizhu,b.id,b.shl,b.lx,b.lxxylb,c.did,gf.credit,
 gf.creditend,gf.rate,gf.id, a.spbh ,a.spmch ,a.shpchd,a.danwbh,a.dwmch,
 a.shpgg ,a.dw ,a.hsje,a.spid,a.jiyili,a.dwbh,a.cgfzr,a.orgid,e.annual_TotalSales

) a
        left join (select djbh,sum(jsje) as jsje,spid,lxflid  
   from dbo.fl_xsdjbhtemp 
      group by djbh,spid,lxflid) c
        on a.djbh=c.djbh and a.spid=c.spid and a.id=c.lxflid
left join (select djbh,sum(jsje) as jsje,spid,lxflid  
   from dbo.fl_xsdjbh  where iszx=3
      group by djbh,spid,lxflid) b
on a.djbh=b.djbh and a.spid=b.spid and a.id=b.lxflid
left join dbo.fl_cg_new_v g on a.lxbynxseid=g.id
left join dbo.fl_cg_new_v h on a.lxbynxseid_contract=h.id



      where a.yesfltj=1  
      and a.rq>=@vars_rq and a.rq<=@vare_rq
      and a.spbh like @varspbh+'%'
and a.danwbh like @vardanwbh+'%'
and a.shpchd like'%'+@varcd+'%'
and a.orgid=@varorgid
   and (xinyongleibie<0 or (g.cridit_type=@varxylb or a.lxxylb=@varxylb))


end


代码稍微比较繁琐,所以删掉了一些字段和关联表,大侠们随意看看就好。
实验结果表明,如果将WHERE语句中的参数改为固定值‘2014-2-8’等,存储过程执行时间为7s钟;
如果传递参数‘2014-2-8’执行存储过程,执行时间为30分钟左右。

网上查询到了参数嗅探等问题,不是很理解。。。
http://blog.****.net/emili/article/details/2192081使用了这位大侠的方法,但是没有解决问题~~
求帮忙!!
------解决思路----------------------
建议把查询语句拆分为若干个子查询,子查询结果分别存为临时表.最后再关联起来.
------解决思路----------------------
存储过程执行速度慢,该怎么处理  这函数也太多了。。

没研究,不过看起来有些建议。

1.最外层的条件,其实有些是可以在内层查询里面过滤的,因为表dbo.buisnessData_lx 在里面是左连接
where a.yesfltj=1  
and a.rq>=@vars_rq and a.rq<=@vare_rq
and a.spbh like @varspbh+'%'
    and a.danwbh like @vardanwbh+'%'
    and a.shpchd like'%'+@varcd+'%'
    and a.orgid=@varorgid
and (xinyongleibie<0 or (g.cridit_type=@varxylb or a.lxxylb=@varxylb))



2. 内层的一些条件,其实可以简化
		where spid=a.spid
and ltrim(rtrim(substring(beizhu,charindex('?',beizhu)+1,20)))=
case when len(ltrim(rtrim(substring(beizhu,charindex('?',beizhu)+1,20))))=6 then left(ltrim(rtrim(a.danwbh)),6)
else  ltrim(rtrim(a.danwbh)) end and charindex('?',beizhu)>0)



3. 这种,and两边的判断其实是一样了吧,重复
when len(ltrim(rtrim(b.beizhu)))=6 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),6) then 1
when len(ltrim(rtrim(b.beizhu)))=5 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),5) then 1
when len(ltrim(rtrim(b.beizhu)))=4 and ltrim(rtrim(b.beizhu))=left(ltrim(rtrim(a.danwbh)),4) then 1


4. 这两个为同一个表,可以不用查询两次
	left join dbo.fl_lx_v b on  (a.spid=b.spid and a.orgid=b.orgid and  DATEDIFF(DAY,b.ksrq,a.rq)>=0 and DATEDIFF(DAY,a.rq,b.zzrq)>=0)
where not exists(
select spid,beizhu 
from dbo.fl_lx 


最后还是看看执行计划,看表被访问的次数,返回的数据量。

表尽量访问1次就行;如果最终数据比较少,读表时却很多,肯定可以提前筛选掉;
为了防止重编译,可以用sp_executesql来参数化;





------解决思路----------------------
聚集索引扫描和表扫描都是要遍历全表,只不过一个上面有聚集索引,另一个是堆表。光知道这个分析不了问题啊,要不然你就把执行计划都贴上来。存储过程执行速度慢,该怎么处理