Stored Procedure
CREATE procedure [dbo].[ImproveProcedure] (@port varchar(50), @portdate datetime)
as
Declare @intdate datetime
select @intdate = max(rate_date) from Interestrate where rate_type = 'Zero'
and rate_date <= @portdate
Update transactiontable set NonDiscount = null, Discount = null, NonDiscountTcurr = null, DiscountTcurr = null,
NonDiscountNew = null, DiscountNew = null
where
port = @port and portdate = @portdate
Update tr set NonDiscount = (case sss_ind when 'P' then -exposure else exposure end) *
dbo.Foo(ccd, 'USD', @portdate,
case when datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature))) < 1 then 1
when datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature))) > 48 then 48
else datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature)))
end),
NonDiscountTcurr = (case sss_ind when 'P' then -exposure else exposure end)
from
Phy p1
where
port = @port and portdate = @portdate
and
tr.trans = p1.trans
and
p1.Sub <> 'Option'
Update tr set NonDiscount = (case when buysell in ('A', 'S') then -vol * markprice else vol * markprice end) *
dbo.Foo(ccd, 'USD', @portdate,
case when datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature))) < 1 then 1
when datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature))) > 48 then 48
else datediff(m, portdate, isnull(priceend1, isnull(priceend2, mature)))
end),
NonDiscountTcurr = (case when buysell in ('A', 'S') then -vol * markprice else vol * markprice end)
from
Phy p1
where
port = @port and portfolio = @portfolio
and
tr.trans = p1.trans
and
p1.Sub = 'Option'
CREATE function [dbo].[Foo]
(@currency1 varchar(10),
@currency2 varchar(10),
@portdate datetime, @month int) returns float
As
BEGIN
Declare
@CurrentRate float,
@Ratedate datetime
select @Ratedate = max(rate_date) from fx where
(
currency1 = @currency1 and currency2 = @currency2 and forward_month = @month
or
currency2 = @currency1 and currency1 = @currency2 and forward_month = @month
)
and
@portdate >= Rate_date
IF exists ( select * from fx where currency1 = @currency1
and currency2 = @currency2 and rate_date = @Ratedate and forward_month = @month)
SELECT @CurrentRate = Rate from fx where currency1 = @currency1 and
currency2 = @currency2 and rate_date = @Ratedate and forward_month = @month
ELSE
IF exists ( select * from fx where currency1 =
@currency2 and currency2 = @currency1 and rate_date = @Ratedate and forward_month = @month)
select @CurrentRate = 1/Rate from fx where currency1 = @currency2
and currency2 = @currency1 and rate_date = @Ratedate and forward_month = @month
ELSE
select @CurrentRate = 1
return (@CurrRate )
END
I understand that scalar function calls can limit the performance of a query. Can someone see a way to remove the function calls, replacing them with a JOIN
or CROSS APPLY
or something instead, to see if this helps performance? I've tried, but haven't been able to find a way.
More info about current performance: A single run of the procedure, updating ~25,000 rows, takes 20-25 minutes to run. Looking at the execution plan, I see a lot of reads tied up in the function, and I'm thinking that with a JOIN
solution (or some such), that number of reads would drop dramatically, and the performance may improve. Plus, as noted above, I've heard scalar function calls are (in general) "bad" in queries.