Problem description
Analyse how unique index join is cached by tracing T-SQL statements sent to MS SQL Server and using
wasCached method.Hints
Use the following code and trace
RPC:Completed events in SQL Server Profiler.static void TestJoinCache(Args _args) { CustTable custTable; CustGroup custGroup; select AccountNum, PaymMode from custTable join custGroup, PaymTermId from custGroup where custTable.AccountNum == "US-004" && custGroup.CustGroup == custTable.CustGroup; info(strFmt("CustTable from %1, CustGroup from %2", custTable.wasCached(), custGroup.wasCached())); } |
The following settings can be used in SQL Server Profiler
Client cache
1. Restart AOS.
2. Run
TestJoinCache job for the first time.T-SQL statement:
SELECT T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.CUSTGROUP, ... (all fields are selected) T2.CUSTGROUP,T2.NAME,T2.CLEARINGPERIOD, ... (all fields are selected) FROM CUSTTABLE T1 CROSS JOIN CUSTGROUP T2 WHERE ((T1.PARTITION=@P1) AND (T1.DATAAREAID=@P2)) AND (((T2.PARTITION=@P3) AND (T2.DATAAREAID=@P4)) AND ((T1.ACCOUNTNUM=@P5) AND (T2.CUSTGROUP=T1.CUSTGROUP))) |
CustTable has Found in CacheLookup, that's why all fields are fetched from the database, nevertheless only AccountNum and PaymMode are requested in X++ statement.CustGroup has EntireTable in CacheLookup, that's why all fields are fetched from the database. I would expect all records of CustGroup table to be selected, but only one is in fact.Infolog message:
"CustTable from NotCached, CustGroup from NotCached".
For the first time records are fetched from the database - it is logical.
3. Run the job for the second time.
T-SQL statement:
there are no calls.
Infolog message:
"CustTable from RecordCached, CustGroup from RecordCached"
Both records are fetched from client cache. Entire
CustGroup table was not cached, that's why wasCached method returned RecordCached value.Server cache
1. Create
TestJoinCache class with such method:public server static void serverCall() { CustTable custTable; CustGroup custGroup; select AccountNum, PaymMode from custTable join custGroup, PaymTermId from custGroup where custTable.AccountNum == "US-004" && custGroup.CustGroup == custTable.CustGroup; info(strFmt("CustTable from %1, CustGroup from %2", custTable.wasCached(), custGroup.wasCached())); } |
2. Create
TestJoinCacheServer job to call the method on server:static void TestJoinCacheServer(Args _args)
{
TestJoinCache::serverCall();
}
|
3. Restart AOS.
4. Run the job for the first time.
T-SQL statement:
SELECT T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.CUSTGROUP, ... (all fields are selected) T2.CUSTGROUP,T2.NAME,T2.CLEARINGPERIOD, ... (all fields are selected) FROM CUSTTABLE T1 CROSS JOIN CUSTGROUP T2 WHERE ((T1.PARTITION=@P1) AND (T1.DATAAREAID=@P2)) AND (((T2.PARTITION=@P3) AND (T2.DATAAREAID=@P4)) AND ((T1.ACCOUNTNUM=@P5) AND (T2.CUSTGROUP=T1.CUSTGROUP))) |
Infolog message:
"CustTable from NotCached, CustGroup from NotCached".
The same as client cache.
5. Run the job for the second time.
T-SQL statement:
SELECT T1.CUSTGROUP,T1.NAME,T1.CLEARINGPERIOD, ... (all fields are selected) FROM CUSTGROUP T1 WHERE ((PARTITION=@P1) AND (DATAAREAID=@P2)) |
CustTable record has been already cached. CustGroup is going to be cached, that's why all records in the current company are fetched from the database.Infolog message:
"CustTable from RecordCached, CustGroup from TableCached"
CustTable and CustGroup are fetched from cache.6. Run the job for the third time.
T-SQL statement:
there are no calls.
Infolog message:
"CustTable from RecordCached, CustGroup from TableCached"
Both records are fetched from cache.
Infolog messages look a bit strange to me. I expected values like: SrvRecordCached or SrvTableCached, but we can analyse it in an another post.
Conclusion
Unique index join is cached differently based on where a select statement is called for the first time - client or server side.
If the select statement is called on client, then both records are cached and next call will use cache to get the records.
If the select statement is called on server, then the second call can cache an entire table and following calls will use cache to get the records.



No comments:
Post a Comment