Backend on the cloud using SQL Server Express 2008 R2 Frontend on Access 2013
I had a query that I recently had to add a subquery to to restrict the results. The query took about 1 second to run before, but now takes about 70+. I think the problem may be that I am using views in the query that are not indexed. I'm pretty new to this and don't use Access/SQL much, so apologies if i am missing something obvious here.
This is my query code:
SELECT DISTINCT vuSearch.PAID ,vuSearch.PDID ,ConcatAddress(Nz([Building_Name]), Nz([Building_No]), Nz([Street]), Nz([IndEst]), Nz([District]), Nz([Town]), Nz([Postcode])) AS Address ,vuSearch.Deal_Date ,vuSearch.Lease_End ,vuSearch.Break_Date ,vuSearch.Review_Date ,vuSearch.PropertyType ,vuSearch.Acting_For ,vuSearch.Landlord_Seller ,vuSearch.Tenant_Purchaser ,IIf(IsNull([vuSearch.GIA]), [vuSearch.NIA], [vuSearch.GIA]) AS MainArea ,vuDesc.Comments_Incentives ,tldDealSearch.Include ,vuSearch.Incomplete FROM ( vuSearch RIGHT JOIN tldDealSearch ON vuSearch.PDID = tldDealSearch.PDID ) LEFT JOIN vuDesc ON tldDealSearch.PDID = vuDesc.PDID WHERE ( ( (vuSearch.PDID) IN ( ( SELECT Max(v2.PDID) FROM vuSearch AS v2 GROUP BY v2.PAID ) ) ) AND ((vuSearch.Incomplete) = False) );
I added indexes to the tldDealSearch table for the PDID and Include fields (I think I've done that right). When I looked at the views on the backend however I could not add indexes as the views are no schema bound.
Is there anything I can do or should be looking at to speed this up? I'm quite worried as right now there are only 300 records on the database - 70+ seconds?
I have checked everything on the 'Analyze performance' tool but not sure what to do next.
EDIT: Thanks for the fast responses guys.
NZ - This is the Access NullToZero function i believe, or what replaced it. http://www.techonthenet.com/access/functions/advanced/nz.php
ConcatAddress - This is a function I use to put all elements of an address together in a readable format for inclusion in a report.
Public Function ConcatAddress(strBuildingName As String, strBuildingNo As String, strStreet As String, _ strIndEstate As String, strDistrict As String, strTown As String, strPostcode As String) As String On Error GoTo ErrRoutine Dim strSQL As String If Len(strBuildingName) > 0 Then strSQL = strBuildingName End If If Len(strBuildingNo) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strBuildingNo Else strSQL = strBuildingNo End If End If If Len(strStreet) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strStreet & "," Else strSQL = strStreet End If End If If Len(strIndEstate) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strIndEstate & "," Else strSQL = strIndEstate End If End If If Len(strDistrict) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strDistrict & "," Else strSQL = strDistrict End If End If If Len(strTown) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strTown Else strSQL = strTown End If End If If Len(strPostcode) > 0 Then If Len(strSQL) > 0 Then strSQL = strSQL & " " & strPostcode Else strSQL = strPostcode End If End If If Len(strSQL) > 0 Then ConcatAddress = strSQL Else ConcatAddress = "" End If ErrExit: Exit Function ErrRoutine: ConcatAddress = Empty Select Case Err Case 94 'MsgBox "Postcode not found." Resume ErrExit Case Else MsgBox "The following error has occurred " & Err & " " & Err.Description Resume ErrExit End Select End Function
'#'#'#'#'#'#'
EDIT
I was asked to post the execution plan for the query, but that is not available in access. I got a hack working that I think is close to what an execution plan is (couldn't get it to work with Access 2013 though).
[For Info]
Add a key and string to the registry - HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines
Add key 'Debug' and add string 'JETSHOWPLAN' - Set the value to ON to record
(results should be in my documents or in location of database)
- Inputs to Query - ODBC table 'vuSearch' ODBC table 'vuSearch' Table 'tldDealSearch' ODBC table 'vuDesc' - End inputs to Query - 01) Sort table 'vuDesc' 02) Outer Join table 'tldDealSearch' to result of '01)' using temporary index join expression "tldDealSearch.PDID=vuDesc.PDID" 1614631268) Remote SQL 03) Sort result of '02)' 04) Inner Join result of '02)' to result of '03)' using temporary index join expression "tldDealSearch.PDID=vuSearch.PDID" store result in temporary table
Seems to be alot of sorting going on so that must slow it down some. Hope this is what you were looking for.
EDIT
The Access JETSHOWPLAN does not give much detail so I transferred the tldSearchData table to the backend and ran the query there. I removed the concatAdderss (as it uses Access function) and also the IIF formula to determine which area to use. The resultant execution plans are below.
Actual: https://drive.google.com/file/d/0B5o8fYhuyQ0ZODZCWHNIaS1KZ1k/view?usp=sharing
Estimated: https://drive.google.com/file/d/0B5o8fYhuyQ0ZU0lnRUhvaXVkc1k/view?usp=sharing
The query took 19 seconds to run directly from SQL (from the cloud server)
ConcatAddress
– Giorgi Nakeuri