Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 SUM(function) slow?

Author  Topic 

buus
Starting Member

4 Posts

Posted - 2007-03-24 : 12:25:57
I was investigating a slow stored procedure today, and came across
some strange behavior. I have a function inside a SUM. It seems that
if instead of SUMing the function, I insert the results into a
temporary table and then SUM the contents of the temporary table, the
query is 2x faster!

Query 1: Old query
SELECT SUM(dbo.GetFileBalanceFunc(L.LedgerID, FileID, @StartDate))
FROM Ledger L
JOIN FileBalance FB ON FB.LedgerID = L.LedgerID
WHERE L.BankAccountID = @BankAccountID

Query 2: New query, 2x faster
create table #foo (x decimal(15,2))
INSERT INTO #foo
SELECT dbo.GetFileBalanceFunc(L.LedgerID, FileID, @StartDate)
FROM Ledger L
JOIN FileBalance FB ON FB.LedgerID = L.LedgerID
WHERE L.BankAccountID = @BankAccountID

SELECT SUM(x) FROM #foo
drop table #foo

Does anyone know why this would be the case? Seems quite odd, as if
the function is being executed twice instead of once..? Thanks for
any insights!

Bryan

khtan
In (Som, Ni, Yak)

17689 Posts

Posted - 2007-03-24 : 12:34:59
what does the query execution plan says ?


KH

Go to Top of Page

buus
Starting Member

4 Posts

Posted - 2007-03-24 : 13:12:06
Sorry, I should have anticipated that question!

Slow query:
---------------------------------------- 
464067.90

(1 row(s) affected)

Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
----------- ----------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ --------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------ ------------------------ ------------------------ ----------- ------------------------ ------------------------------------ -------- ------------------------------ -------- ------------------------
1 1 SELECT SUM(dbo.GetFileBalanceFunc(L.LedgerID, FileID, @StartDate))
FROM Ledger L
JOIN FileBalance FB ON FB.LedgerID = L.LedgerID
WHERE L.BankAccountID = @BankAccountID

155187 1 0 NULL NULL NULL NULL 1.0 NULL NULL NULL 0.28155702 NULL NULL SELECT 0 NULL
1 1 |--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else [Expr1008])) 155187 2 1 Compute Scalar Compute Scalar DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else [Expr1008]) [Expr1002]=If ([Expr1007]=0) then NULL else [Expr1008] 1.0 0.0 3.161167E-4 24 0.28155702 [Expr1002] NULL PLAN_ROW 0 1.0
1 1 |--Stream Aggregate(DEFINE:([Expr1007]=COUNT_BIG([dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate])), [Expr1008]=SUM([dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate])))) 155187 3 2 Stream Aggregate Aggregate NULL [Expr1007]=COUNT_BIG([dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate])), [Expr1008]=SUM([dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate])) 1.0 0.0 3.161167E-4 24 0.28155702 [Expr1007], [Expr1008] NULL PLAN_ROW 0 1.0
9799 1 |--Hash Match(Inner Join, HASH:([L].[LedgerID])=([FB].[LedgerID])) 155187 4 3 Hash Match Inner Join HASH:([L].[LedgerID])=([FB].[LedgerID]) NULL 3161.167 0.0 0.10900188 19 0.28124088 [L].[LedgerID], [FB].[FileID] NULL PLAN_ROW 0 1.0
1 1 |--Clustered Index Scan(OBJECT:([ResWare].[dbo].[Ledger].[Ledger_PK] AS [L]), WHERE:([L].[BankAccountID]=[@BankAccountID])) 155187 5 4 Clustered Index Scan Clustered Index Scan OBJECT:([ResWare].[dbo].[Ledger].[Ledger_PK] AS [L]), WHERE:([L].[BankAccountID]=[@BankAccountID]) [L].[BankAccountID], [L].[LedgerID] 1.1666667 3.7578501E-2 8.6200002E-5 64 0.0376647 [L].[BankAccountID], [L].[LedgerID] NULL PLAN_ROW 0 1.0
19414 1 |--Clustered Index Scan(OBJECT:([ResWare].[dbo].[FileBalance].[FileBalance_PK] AS [FB])) 155187 6 4 Clustered Index Scan Clustered Index Scan OBJECT:([ResWare].[dbo].[FileBalance].[FileBalance_PK] AS [FB]) [FB].[LedgerID], [FB].[FileID] 19414.0 0.11313406 2.1433899E-2 52 0.13456796 [FB].[LedgerID], [FB].[FileID] NULL PLAN_ROW 0 1.0

(6 row(s) affected)


Fast Query:
(9799 row(s) affected)

Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
----------- ----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------- ------------------------ ------------------------ ------------------------ ----------- ------------------------ ------------------------------------ -------- ------------------------------ -------- ------------------------
9799 1 INSERT INTO #foo
SELECT dbo.GetFileBalanceFunc(L.LedgerID, FileID, @StartDate)
FROM Ledger L
JOIN FileBalance FB ON FB.LedgerID = L.LedgerID
WHERE L.BankAccountID = @BankAccountID
103463 1 0 NULL NULL NULL NULL 3161.167 NULL NULL NULL 0.36416414 NULL NULL INSERT 0 NULL
9799 1 |--Table Insert(OBJECT:([tempdb].[dbo].[#foo________________________________________________________________________________________________________________00000000D3A3]), SET:([#foo].[x]=[Expr1002])) 103463 2 1 Table Insert Insert OBJECT:([tempdb].[dbo].[#foo________________________________________________________________________________________________________________00000000D3A3]), SET:([#foo].[x]=[Expr1002]) NULL 3161.167 1.6756756E-2 3.1611668E-3 15 0.36416414 NULL NULL PLAN_ROW 0 1.0
9799 1 |--Table Spool 103463 3 2 Table Spool Eager Spool NULL NULL 3161.167 6.1234985E-2 1.1381201E-3 16 0.34424624 [Expr1002] NULL PLAN_ROW 0 1.0
9799 1 |--Top(ROWCOUNT est 0) 103463 4 3 Top Top NULL NULL 3161.167 0.0 3.161167E-4 16 0.28187314 [Expr1002] NULL PLAN_ROW 0 1.0
9799 1 |--Compute Scalar(DEFINE:([Expr1002]=[dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate]))) 103463 5 4 Compute Scalar Compute Scalar DEFINE:([Expr1002]=[dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate])) [Expr1002]=[dbo].[GetFileBalanceFunc]([L].[LedgerID], [FB].[FileID], [@StartDate]) 3161.167 0.0 3.161167E-4 16 0.28155702 [Expr1002] NULL PLAN_ROW 0 1.0
9799 1 |--Hash Match(Inner Join, HASH:([L].[LedgerID])=([FB].[LedgerID])) 103463 6 5 Hash Match Inner Join HASH:([L].[LedgerID])=([FB].[LedgerID]) NULL 3161.167 0.0 0.10900188 19 0.28124088 [L].[LedgerID], [FB].[FileID] NULL PLAN_ROW 0 1.0
1 1 |--Clustered Index Scan(OBJECT:([ResWare].[dbo].[Ledger].[Ledger_PK] AS [L]), WHERE:([L].[BankAccountID]=[@BankAccountID])) 103463 7 6 Clustered Index Scan Clustered Index Scan OBJECT:([ResWare].[dbo].[Ledger].[Ledger_PK] AS [L]), WHERE:([L].[BankAccountID]=[@BankAccountID]) [L].[BankAccountID], [L].[LedgerID] 1.1666667 3.7578501E-2 8.6200002E-5 64 0.0376647 [L].[BankAccountID], [L].[LedgerID] NULL PLAN_ROW 0 1.0
19414 1 |--Clustered Index Scan(OBJECT:([ResWare].[dbo].[FileBalance].[FileBalance_PK] AS [FB])) 103463 8 6 Clustered Index Scan Clustered Index Scan OBJECT:([ResWare].[dbo].[FileBalance].[FileBalance_PK] AS [FB]) [FB].[LedgerID], [FB].[FileID] 19414.0 0.11313406 2.1433899E-2 52 0.13456796 [FB].[LedgerID], [FB].[FileID] NULL PLAN_ROW 0 1.0

(8 row(s) affected)


----------------------------------------
464067.90

(1 row(s) affected)

Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
----------- ----------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- ----------- ------------------------------ ------------------------------ ----------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------- ------------------------ ------------------------ ------------------------ ----------- ------------------------ ----------------------- -------- ------------------------------ -------- ------------------------
1 1 SELECT SUM(x)
FROM #foo 103464 1 0 NULL NULL NULL NULL 1.0 NULL NULL NULL 3.7658349E-2 NULL NULL SELECT 0 NULL
1 1 |--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1003]=0) then NULL else [Expr1004])) 103464 2 1 Compute Scalar Compute Scalar DEFINE:([Expr1002]=If ([Expr1003]=0) then NULL else [Expr1004]) [Expr1002]=If ([Expr1003]=0) then NULL else [Expr1004] 1.0 0.0 0.00000025 24 3.7658349E-2 [Expr1002] NULL PLAN_ROW 0 1.0
1 1 |--Stream Aggregate(DEFINE:([Expr1003]=COUNT_BIG([#foo].[x]), [Expr1004]=SUM([#foo].[x]))) 103464 3 2 Stream Aggregate Aggregate NULL [Expr1003]=COUNT_BIG([#foo].[x]), [Expr1004]=SUM([#foo].[x]) 1.0 0.0 0.00000025 24 3.7658349E-2 [Expr1003], [Expr1004] NULL PLAN_ROW 0 1.0
9799 1 |--Table Scan(OBJECT:([tempdb].[dbo].[#foo________________________________________________________________________________________________________________00000000D3A3])) 103464 4 3 Table Scan Table Scan OBJECT:([tempdb].[dbo].[#foo________________________________________________________________________________________________________________00000000D3A3]) [#foo].[x] 1.0 3.7578501E-2 7.9600002E-5 16 3.7658099E-2 [#foo].[x] NULL PLAN_ROW 0 1.0

(4 row(s) affected)
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2007-03-24 : 13:17:56
Post the function code.


Peter Larsson
Helsingborg, Sweden
Go to Top of Page

buus
Starting Member

4 Posts

Posted - 2007-03-24 : 13:32:59
Here you go...
CREATE FUNCTION dbo.GetFileBalanceFunc (@LedgerID int, @FileID int, @AtDate DATETIME) RETURNS Decimal(15,2)
AS

BEGIN

DECLARE @UpdateDate DATETIME
DECLARE @Balance Decimal(15,2)
SELECT @UpdateDate = ChangeDate, @Balance = Balance FROM FileBalance WHERE FileID = @FileID AND LedgerID = @LedgerID

-- Need to calculate the balance if our date is later than the date we are looking for
IF(@UpdateDate >= @AtDate OR @UpdateDate IS NULL)
BEGIN
SET @Balance = NULL

SELECT @Balance = ISNULL(SUM(LEI.Amount), 0)
FROM LedgerEntry LE
JOIN LedgerEntryItem LEI ON LEI.LedgerEntryID = LE.LedgerEntryID
WHERE FileID = @FileID
AND LedgerID = @LedgerID
AND ((TransactionTypeID = 5 AND LE.IssueDate < @AtDate)
OR (TransactionTypeID <> 5 AND LE.CreateDate < @AtDate))

SET @Balance = @Balance -
ISNULL((SELECT SUM(Amount)
FROM LedgerEntry LE
JOIN LedgerEntryItem LEI ON LEI.LedgerEntryID = LE.LedgerEntryID
JOIN Invoice I ON I.InvoiceID = LE.InvoiceID AND I.IsVoid = 0
WHERE LE.TransactionTypeID = 4 AND LE.InvoiceID = I.InvoiceID AND LE.FileID = @FileID AND LE.LedgerID = @LedgerID AND LE.CreateDate < @AtDate), 0)

SET @Balance = @Balance +
ISNULL((SELECT SUM(Amount)
FROM InvoicePayment IP
JOIN Invoice I ON I.InvoiceID = IP.InvoiceID AND I.IsVoid = 0
JOIN LedgerEntry LE ON LE.InvoiceID = I.InvoiceID AND TransactionTypeID = 4 AND LE.FileID = @FileID AND LE.LedgerID = @LedgerID
WHERE IP.PaymentDate < @AtDate), 0)

END

IF @Balance IS NULL
SET @Balance = 0

RETURN(@Balance)
Go to Top of Page

buus
Starting Member

4 Posts

Posted - 2007-03-24 : 13:38:22
One other odd thing that I noticed. About an hour ago, when I first
performed this analysis, the slow query was taking 8 seconds, and the
fast one 4 seconds. Now the slow one is taking 1 minute, and the fast
one is taking 22 seconds.

The stored procedure is also called from an application, and from the
application it's still only taking 4 seconds, while in query analyzer
it's taking 22 seconds.

Any idea what would cause such a thing, or ideas about how to track down
what might be causing it? I should probably start up the profiler and
run it both ways to see what's different. Hmm..
Go to Top of Page
   

- Advertisement -