Their 'Creditor Balance As At' report was taking a couple of hours to run, and sometimes crashing. So they asked me to take a look.
The SP in question is usp_JIWA_Creditors_AgedBalancesSummary.
This calls usp_JIWA_Creditors_CreditorBalanceAsAt in a loop.
After much 'tuning', I had a version that was performing much better, with the loop replaced with a set-based update using a table-value-function version of usp_JIWA_Creditors_CreditorBalanceAsAt .
I then started doing some small batches to confirm that I was getting results that match the stock version.
But when I compared the performance of usp_JIWA_Creditors_CreditorBalanceAsAt with my table-value-function version in small batches. Or even one creditor at a time, the difference could not explain the performance difference between the stock usp_JIWA_Creditors_AgedBalancesSummary and my version when running a large batch.
So I set about adding some timing "instrumentation" to both the stock and my version, and modified my version back to using a loop so that I could time both versions of usp_JIWA_Creditors_CreditorBalanceAsAt (which are really very similar).
After doing this, the stock one can now run the full set in under 90 seconds. Instead of taking 2 1/2 hours.
And yet "all" I'd done is add some timing collection code around the call to usp_JIWA_Creditors_CreditorBalanceAsAt.
SQL Server can be really, really, weird sometimes.
So I went through, rewinding the instrumentation code, to figure out what did it.
What was the magical change?
Replacing this:
- Code: Select all
SET @CurrentCreditorID = (SELECT TOP 1 CreditorID FROM @CreditorIDTable ORDER BY CreditorID)
with this
- Code: Select all
SELECT TOP 1 @CurrentCreditorID = CreditorID FROM @CreditorIDTable
at about line 120 (depends on how your UI scripts it).
I had changed it to this so that I could add the account number and name to my timing message:
- Code: Select all
select top (1) @CurrentCreditorID = CreditorID
, @currentCreditorAccount = AccountNo
, @currentCreditorName = CreditorName
from @CreditorIDTable
order by CreditorName;
(I did try it with different ORDER BY clauses; they make neglible difference)