sql server - Performance on an update/delete query -


i want update table values generated out of same table.

my goal search rows proftxt _ns , _wp , same ao, sum them up,
divide value through number of _h,_g,_l-elements of ao , add value _h, _g , _l objects of ao.

it possible there _ns , _wp rows ao. routine should jump on ao.

example:

my data looks like:

an, ao, proftxt, value, year   101 , 1, 'e_nse', 5, 2006   102 , 1, 'e_ha', 1, 2006   103 , 1, 'w_nsr', 4, 2006    104 , 2, 'w_nsr', 2, 2006   105 , 2, 'x_h05r', 4, 2006    106 , 2, 'w_gr', 2, 2006    107 , 2, 'a_wpr', 4, 2006   108 , 3, 'a_wpr', 4, 2006  

my data should like:

an, ao, proftxt, value, year   102 , 1, 'e_ha', 10 2006    103 , 2, 'x_h05r', 7, 2006   103 , 2, 'w_gr', 5, 2006    108 , 3, 'a_wpr', 4, 2006   

my routine works small amount of testdata.

the update function ends, while working on real database, after 13 hours successful.
edited 5000 out of 210000 rows.

declare @endyear int declare @ao bigint declare @year int declare @elements int  --parameter festlegen set @year = 2006 set @endyear = 2013 --endyear+1   set @ao = 2    while(@year<@endyear) begin      while (@ao >1)  --do long cursor inside table begin       set @ao = (select top 1 ao tbl_slp -- search ao _wp _ns                  (proftxt '%[_]wp%'                           or proftxt '%[_]ns%')                           , year = @year                           , ao > @ao );      set @elements = (select count(proftxt) --count number of _h, _g, _l elements                             tbl_slp                               ao = @ao , year = @year ,                                   (proftxt '%[_]h%' or proftxt = null                                   or proftxt '%[_]g%'                                   or proftxt '%[_]l%'))      if (@elements != 0)     begin         update tbl_slp --update _h, _g, _l rows         set value = value + (select sum(convert(float, value))                              tbl_slp                             (proftxt '%[_]wp%'                                                             or proftxt '%[_]ns%')                                                             , year = @year                                                              , ao = @ao)                             /@elements         ao = @ao , year = @year            delete tbl_slp --delete_wp _ns rows             ao= @ao                    , year = @year                    , (proftxt '%[_]wp%' or proftxt '%[_]ns%')      end      set @ao = @ao +1     end     set @year = @year +1 end 

i know routine super slow, can do?

sql designed set-based operations, not procedural flow-of-control style logic routine. here's set-based way of doing it, i'm guessing faster procedural way:

set xact_abort on set nocount on  begin transaction  -- create temp table each ao-year's sums , counts (sums of _ns , _wp record values , counts of _h, _g, , _l records) select t.ao, t.year, sum(t.value) sumvals, (select count(*) tbl_slp a.ao = t.ao , a.year = t.year , (a.proftxt = null or a.proftxt '%[_]h%' or a.proftxt '%[_]g%' or a.proftxt '%[_]l%')) countother #temp1  tbl_slp t (t.proftxt '%[_]wp%' or t.proftxt '%[_]ns%') group t.ao, t.year  -- add "sum/count" each ao-year _h, _g, , _l records year update set value = value + convert(float, t.sumvals) / t.countother tbl_slp  inner join #temp1 t on a.ao = t.ao , a.year = t.year (a.proftxt = null or a.proftxt '%[_]h%' or a.proftxt '%[_]g%' or a.proftxt '%[_]l%')  -- we've distributed _wp , _ns values, delete records delete tbl_slp inner join #temp1 t on a.ao = t.ao , a.year = t.year (a.proftxt '%[_]wp%' or a.proftxt '%[_]ns%')  , t.countother > 0  commit transaction 

for sample set gave, produces exact same results (except an column assume typo).

full disclosure, takes longer on sample set routine (17 ms compared 3 ms), should scale large data whole lot better. put in transaction correctness i'm not sure exact use case is, may disadvantage of way since lock pages (and may escalate whole table) entire time. routine didn't have transactions, though, lead bad data if keep way make sure put each update-delete pair in own transaction.

also, if don't have index on proftxt, add one! make huge difference both solutions.

good luck. here's the sql fiddle used.


Comments