SQL Server - 减少读取次数

Nem*_*cic 1 sql t-sql sql-server stored-procedures query-optimization

我有一个关于SQL Server优化的一般问题:如何减少存储过程中的读取次数?

我对以下良好实践感兴趣: - 在物理表和临时表中创建索引 - 使用临时表而不是在程序中使用相同的表几次 - 在DML之前使用DDL - 在存储过程开始时设置NOCOUNT ON - ...

我们遇到的问题是由于存储过程引起的大量读取而使用的磁盘空间,我需要对其进行优化.

"最昂贵"的存储过程的一部分是:

create table #stavke   
(  
    Id_Br int identity(1, 1), IDStavke int, 
    HeaderID int, Currency varchar(3),  GLAcct varchar(20), id varchar(20), Trnuid varchar(60), 
    ReferenceID varchar(20), DocumentID varchar(20),
    DtAvail varchar(10), DtBooking varchar(10), DatePosted varchar(10),
    Amount money, AmountLcl money, 
    Description varchar(250), Type varchar(10), DP int  )
insert into #stavke   
  (  
    IDStavke, HeaderID, GLAcct, Currency, id , Trnuid , 
    ReferenceID, DocumentID ,
    DtAvail , DtBooking , DatePosted,
    Amount , AmountLcl , 
    Description , Type , DP 
  )  

SELECT S.ID as IDStavke,
   z.RB as HeaderID,  
   z.KONTO AS GLAcct,
   z.OZNVAL AS Currency,
   Si.BROJNALOGA as ID,
   D.TRN as Trnuid, 
   case substring(SI.BROJNALOGA,1,4)
        when '0746' then O.REFERENCA
        when '1450' then D.REFERENCA
        when '0743' then L.REFERENCA
        when '2021' then N.REFERENCA
   end   ReferenceID,
   case substring(SI.BROJNALOGA,1,4)
        when '3000' then 'Kursna razlika'
        when '2200' then 'PP-'+SI.BROJNALOGA
        when '2201' then 'KDP-'+SI.BROJNALOGA
        else SI.BROJNALOGA
   end DocumentID,
   dvalute as DtAvail, 
   si.dknizenja as DtBooking, 
   '' as DatePosted,        
   case si.teret
        when 0 then si.korist
        else si.teret 
   end Amount, 
   case SI.DINTERET
        when 0 then si.dinkorist
        else si.dinteret 
   end AmountLcl, 
   '' as Description,
   case substring(SI.BROJNALOGA,1,4)
        when '0746' then '0746'
        when '1450' then '1450'
        when '0743' then '0743'
        when '2021' then  'Ostalo'
   end  Type,
   case SI.DINTERET
        when 0 then 1
        else -1 
   end DP
FROM       A I
inner join B st on i.transfer=st.transfer and i.partija=st.partija 
INNER JOIN C SI ON st.RB=Si.RB
inner join D z on z.rb=st.rb
inner join E s on z.rb=s.rb AND s.BROJNALOGA = si.BROJNALOGA 
LEFT JOIN  F D ON  D.BROJ=SI.BROJNALOGA
LEFT JOIN  G L ON L.BROJ=SI.BROJNALOGA
LEFT JOIN  H O ON O.BROJ=SI.BROJNALOGA
LEFT JOIN  I N ON N.BROJ=SI.BROJNALOGA 
WHERE I.novi_izvod=convert(int,@StatementNumber) AND i.PARTIJA=@Account 
ORDER BY I.PARTIJA,z.RB,SI.id, z.KONTO,z.OZNVAL, SI.DKNIZENJA
Run Code Online (Sandbox Code Playgroud)

表B,G,H和I(我为此示例更改了表的实名以使其更易于阅读)非常大,即具有许多列和大量数据.

Var*_*han 5

我希望你说的是通过一个程序最小化磁盘活动.

首先,您可以使用以下方式对当前的IO活动进行基准测试

set statistics IO on;
Run Code Online (Sandbox Code Playgroud)

使用该信息并使用SET SHOWPLAN_ALL或XML获取执行计划,或者您可以使用ssms以符合人体工程学的方式获得相同的信息.您可以使用DTA进行基本调整.

尝试将SP作为一系列临时语句执行,并查看IO的重点并集中在该段上.有很多好的做法可能适合您的要求.