Solved

SQL Index

Posted on 2011-09-12
9
359 Views
Last Modified: 2012-06-22
I have the following query which runs against a table with 300,000,000 records. It takes about 2 hours to run which is much too long. The DTH_CallRecordMaster table does already have a non-unique, non-clustered index on CustomerID and the execution plan shows it it is the index seek on the CustomerID index is 95% of the work.

What are my options to improve performance of this query?

Thanks


      
 
select CustomerID, count(CustomerID), sum(CallCost) from DTH_CallRecordMaster (nolock)
		where CallType in (5, 7, 10, 11, 12, 13, 22, 23) and cast(StartTime as date) between '2011-08-01' and '2011-08-31' 
		  and CustomerID in (select CustomerID from DTH_CustomerMaster (nolock) where CycleID = 'MONTHLY-15')
			group by CustomerID

Open in new window

0
Comment
Question by:dthansen
9 Comments
 
LVL 18

Expert Comment

by:x-men
ID: 36524814
have you runned the Database Tunning Advisor?
0
 
LVL 23

Expert Comment

by:Racim BOUDJAKDJI
ID: 36524855
Please post the showplan.
0
 
LVL 12

Assisted Solution

by:jagssidurala
jagssidurala earned 100 total points
ID: 36524929
you can write the above query like below.

select       A.CustomerID,
      count(A.CustomerID),
      sum(A.CallCost)
from       DTH_CallRecordMaster as A WITH(nolock)
Inner
Join      DTH_CustomerMaster as B On B.CustomerID  =  A.CustomerID
where       A.CallType in (5, 7, 10, 11, 12, 13, 22, 23)
and       cast(A.StartTime as date) between '2011-08-01' and '2011-08-31'
and       B.CycleID = 'MONTHLY-15'
group by A.CustomerID

and also create index with following columns calltype, starttime, CustomerId, CallCost for table A abd
Customerid,Cycleid for table B
0
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 

Author Comment

by:dthansen
ID: 36525586
The lookup to the DTH_CustomerMaster for cycleID is 0% if the execution plan. I'm not worried about that.

Should I create a new index with those columns or simply add those columns to the existing index that is on CustomerID?

Thanks.
0
 
LVL 75

Accepted Solution

by:
Anthony Perkins earned 300 total points
ID: 36526681
Make sure you have the following indexes and try is as below:
DTH_CallRecordMaster: CustomerID, CallType, StartTime
DTH_CustomerMaster: CustomerID, CycleID

If that does not make any difference, buy a faster server.
SELECT  r.CustomerID,
        COUNT(*),
        SUM(r.CallCost)
FROM    DTH_CallRecordMaster r (NOLOCK)
        INNER JOIN DTH_CustomerMaster c (NOLOCK) ON r.CustomerID = c.CustomerID
WHERE   r.CallType IN (5, 7, 10, 11, 12, 13, 22, 23)
        AND r.StartTime >= '2011-08-01'
        AND r.StartTime < '2011-08-31'
        AND c.CycleID = 'MONTHLY-15'
GROUP BY r.CustomerID

Open in new window

0
 

Author Comment

by:dthansen
ID: 36527077
1. The CustomerMaster has only 40 rows while the CallRecordMaster has 300,000,000. Isn't joining those tables more expensive than a simple IN against CustomerMaster?

2. Should I add CallType, StartTime to the existing index on CustomerID or create a new index.

3. Why not have 'CallCost' in the index as an include so it is a covering index?

4. Why did you choose to replace the 'between' with a >= and <. Is that more efficient?

Thanks.
0
 
LVL 75

Assisted Solution

by:Anthony Perkins
Anthony Perkins earned 300 total points
ID: 36527163
1. What does the Execution Plan tell you in each case?  Why don't you test it?  Use the one that best fits your requirements.
2. I would define them as Keys in a single index.  But test it out.  Inspect the Execution Plan.
3. Yes.
4. I suspect cast(A.StartTime as date) between '2011-08-01' and '2011-08-31' is not a SARGable function, so I replaced it with something that would take advantage on an index on StartTime.   If you want to leave it then don't bother with adding an index on StartTime, it may not use it.  Hence lousy performance.  Again test and see for yourself.
0
 
LVL 15

Assisted Solution

by:Anuj
Anuj earned 100 total points
ID: 36527258
Make sure that you have proper indexes as keys
CustomerID, CallType,StartTime Include(CallCost)  on DTH_CallRecordMaster
CustomerID, CycleID  On DTH_CustomerMaster

Also, check your indexes are properly defragmented and the statistics are updated.

1. I assume, joining between smaller and larger table use Hash Join, so both IN and Inner join will use Hash Join.
2. CustomerID, CycleID  On DTH_CustomerMaster
3. Including CallCost makes it covered index and remove lookup.
4. SQL Server usually convert between to >= and <=, this will not make any difference. As @Acperkins suggested these arguments may be non sargable so, check your data type of StartTime matches both column and variable.
0
 
LVL 75

Assisted Solution

by:Anthony Perkins
Anthony Perkins earned 300 total points
ID: 36528785
>>SQL Server usually convert between to >= and <=, this will not make any difference.<<
Which reminds me that the condition I posted is not correct:
Instead of:
cast(StartTime as date) between '2011-08-01' and '2011-08-31'
Use:
AND r.StartTime >= '2011-08-01'
AND r.StartTime < '2011-09-01'

That is assuming that the following is not SARGable:
cast(StartTime as date) between '2011-08-01' and '2011-08-31'

0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Why is this different from all of the other step by step guides?  Because I make a living as a DBA and not as a writer and I lived through this experience. Defining the name: When I talk to people they say different names on this subject stuff l…
This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
Via a live example, show how to set up a backup for SQL Server using a Maintenance Plan and how to schedule the job into SQL Server Agent.
Viewers will learn how to use the SELECT statement in SQL to return specific rows and columns, with various degrees of sorting and limits in place.

815 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now