David Emerson
newsgrps at dalyn.co.nz
Tue Apr 4 18:58:11 CDT 2006
Thanks to all who have responded. I am working my way through the suggestions.
I downloaded the trial version of Red-Gate SQL comparison. It only
showed some extended properties as being different in the various
tables, views and sprocs. I synchronized the objects but the problem
still persists.
Using Ken's Test by Destruction method I identified the problem view
as highlighted below:
SELECT dbo.vwAgedDebtorGet.CustomerID,
dbo.vwAgedDebtorGet.StatementID,
dbo.vwAgedDebtorGet.AccountNo, dbo.vwAgedDebtorGet.CustName,
dbo.vwAgedDebtorGet.StatementDate, dbo.vwAgedDebtorGet.StatementNumber,
dbo.vwAgedDebtorGet.AccFreq, dbo.vwAgedDebtorGet.CurrentMth,
dbo.vwAgedDebtorGet.OneMonth,
dbo.vwAgedDebtorGet.TwoMonths,
dbo.vwAgedDebtorGet.ThreeMonths, dbo.vwAgedDebtorGet.NoOverdueNote,
dbo.vwAgedDebtorReceipt.NetReceipts,
dbo.vwAgedDebtorReceipt.GJCredit, dbo.vwAgedDebtorReceiptInv.NetReceiptsInv,
dbo.vwAgedDebtorReceiptInv.GJCreditInv, dbo.vwAgedDebtorGet.MGrpIDNo,
dbo.vwAgedDebtorGet.DDRegistered,
dbo.vwAgedDebtorGet.DDFrequency, dbo.vwAgedDebtorGet.PayArrange,
dbo.vwAgedDebtorReceiptNotPost.ReceiptNotPost AS
ReceiptsNotPosted,
dbo.vwAgedDebtorGet.VIPCust, dbo.vwAgedDebtorGet.AccStatus
FROM dbo.vwAgedDebtorGet INNER JOIN dbo.vwAgedDebtorGetLastStatDate
ON dbo.vwAgedDebtorGet.CustomerID =
dbo.vwAgedDebtorGetLastStatDate.CustIDNo AND
dbo.vwAgedDebtorGet.StatementDate =
dbo.vwAgedDebtorGetLastStatDate.StatementDate LEFT OUTER
JOIN dbo.vwAgedDebtorReceipt ON
dbo.vwAgedDebtorGet.CustomerID = dbo.vwAgedDebtorReceipt.CustIDNo AND
dbo.vwAgedDebtorGet.StatementNumber =
dbo.vwAgedDebtorReceipt.StatNum LEFT OUTER JOIN
dbo.vwAgedDebtorReceiptInv ON dbo.vwAgedDebtorGet.CustomerID =
dbo.vwAgedDebtorReceiptInv.CustIDNo AND
dbo.vwAgedDebtorGet.StatementNumber =
dbo.vwAgedDebtorReceiptInv.InvNum
LEFT OUTER JOIN dbo.vwAgedDebtorReceiptNotPost ON
dbo.vwAgedDebtorGet.CustomerID =
dbo.vwAgedDebtorReceiptNotPost.CustIDNo
This is the whole of the sproc - there are no other where clauses etc.
When I delete this join (and the fields in the SELECT section from
the dbo.vwAgedDebtorReceiptInv view) then the sproc runs in 4 seconds
and returns 680 rows.
When I run the dbo.vwAgedDebtorReceiptInv view within Access it
returns 2780 rows in a couple of second.
Ken asked if the views are indexed. I couldn't see any properties in
SQL2000 in the view for indexing. The StatementNumber and InvNum
fields in the underlying tables are indexed
I have used the dbo.vwAgedDebtorReceiptInv view in other sprocs and
they work in an acceptable time. In all other cases though the join
is to a table, not another view. (However, remember that the same
sproc runs fine in the second database).
The dbo.vwAgedDebtorReceiptInv is not a simple view:
SELECT TOP 100 PERCENT
SUM(ROUND((CASE WHEN TranCode = 'CR' THEN CASE WHEN TranAmt < 0
THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END, 2))
+ SUM(ROUND((CASE WHEN TranCode = 'CN' THEN CASE WHEN
TranAmt < 0 THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END, 2))
+ SUM(ROUND((CASE WHEN TranCode = 'RR' THEN CASE WHEN
TranAmt > 0 THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END,
2)) AS NetReceiptsInv,
SUM(ROUND((CASE WHEN TranCode = 'CR' THEN CASE WHEN TranAmt < 0
THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END,
2)) AS CRReceiptsInv,
SUM(ROUND((CASE WHEN TranCode = 'CN' THEN CASE WHEN TranAmt < 0
THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END,
2)) AS CNReceiptsInv,
SUM(ROUND((CASE WHEN TranCode = 'RR' THEN CASE WHEN TranAmt > 0
THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END,
2)) AS RevReceiptsInv,
SUM(ROUND((CASE WHEN TranCode = 'GJ' THEN CASE WHEN TranAmt < 0
THEN TranAmt ELSE 0 END ELSE 0 END)
* CASE WHEN GSTPayable = 1 THEN (1 + GSTRate) ELSE 1 END,
2)) AS GJCreditInv, dbo.tblGenJournal.LinkIDNo,
dbo.tblGenJournal.CustIDNo, dbo.tblCustInvoice.InvoiceNumber - 1
AS InvNum, dbo.tblCustInvoice.InvoiceDate
FROM dbo.tblGenJournal INNER JOIN dbo.tblCustInvoice ON
dbo.tblGenJournal.LinkIDNo = dbo.tblCustInvoice.InvoiceID
WHERE (dbo.tblGenJournal.TranType = 1)
GROUP BY dbo.tblGenJournal.LinkIDNo, dbo.tblGenJournal.CustIDNo,
dbo.tblCustInvoice.InvoiceNumber - 1, dbo.tblCustInvoice.InvoiceDate
HAVING (dbo.tblCustInvoice.InvoiceNumber - 1 > 0)
ORDER BY dbo.tblGenJournal.LinkIDNo
David
At 4/04/2006, you wrote:
>David,
>
> > I have a stored procedure that is based on a number of views ...
> > In the SQL database that this was developed in it runs fine
> > (in about 30 seconds). However, when I script the objects and
> > restore them into the second database, the same stored procedure
> > runs for over 10 minutes...
>
>It is a little hard to give advice without more information:
>
>* Are the views simple views (SELECTs against a single table) or complex
>(SELECTs against multiple tables)?
>* Are the views indexed?
>* Are you returning a subset of the records in your procedure, or
>everything? (In other words, is there a WHERE clause you are not showing
>us?)
>* What is the distribution of the data? For instance, does
>vwAgedDebtorGet return greatly more or less records than
>vwAgedDebtorGetLastStatDate?
>
>Even without answers to these questions, there is a diagnostic method
>that will almost certainly work: Test by Destruction. To do this:
>
>1. Make copies of your proc on both databases.
>2. On the copies, remove one view at a time from each proc. (start from
>the bottom)
>3. Recreate both procs, and test the response time.
>4. Repeat steps 2-3 until your slower proc performs as expected, or you
>run out of views
>
>The last view you removed, or the last one standing, is the one that is
>introducing the slowdown. Investigate that view, because something about
>it is different between the two databases, or the data it is querying is
>different. If the view is complex, you can test it by destruction using
>the process outlined above to find the table or join that is causing the
>problem.
>
>Test by Destruction is a generic, simple way of isolating problems in
>complex queries.
>
>-Ken
>--
>AccessD mailing list
>AccessD at databaseadvisors.com
>http://databaseadvisors.com/mailman/listinfo/accessd
>Website: http://www.databaseadvisors.com