April 13, 2019 at 10:09 am
Hi
I came across a scenario where a query is picking totally unrelated index in the execution plan. Here is the case:
SELECT A.tranid,A.transittime
FROM table1 A WITH(nolock)
JOIN table2 B WITH(NOLOCK) On (A.tranid=B.TranId and A.ProdType=B.Prodtype )
WHERE A.transittime Between '2017-11-14 23:30:00.000' AND '2018-01-13 23:30:00.000'
There are couple of indexes which are best suited for this query like :
CREATE INDEX IDX1 ON table1(tranid,ProdType,transittime)
CREATE INDEX IDX2 ON table2(tranid,ProdType )
But surprisingly, the query gets below index scan in plan:
CREATE INDEX IDX3 ON table1(Visitduration )
this index column Visitduration is no where part of my query, but still optimizer scans it. Why index IDX1 seek in not happening here? What scenario might cause it? the query return around 200K records.
If I use index hint to force the IDX1 use, then my performance gets slower compared to IDX3 use.
Any thoughts?
Online Trainer For SQL DBA and Developer @RedBushTechnologies with 18 yrs exp.
April 13, 2019 at 10:20 am
Can you post the DDL of your tables please? Please also make sure to use the "Insert/edit code sample" button to make it readable too. I can't replicate the problem on my sandbox:
USE Sandbox;
GO
CREATE TABLE table1 (tranid int,
transittime datetime,
ProdType int,
Visitduration time);
CREATE TABLE table2 (SomeID int,
Tranid int,
ProdType int);
CREATE INDEX IDX1 ON table1(tranid,ProdType,transittime);
CREATE INDEX IDX2 ON table2(tranid,ProdType );
CREATE INDEX IDX3 ON table1(Visitduration );
GO
INSERT INTO Table1
VALUES(1,'2017-12-17T17:15:00.000',7,'01:17');
INSERT INTO Table2
VALUES(1,1,7);
GO
SELECT A.tranid,A.transittime
FROM table1 A
JOIN table2 B ON A.tranid=B.TranId
AND A.ProdType=B.Prodtype
WHERE A.transittime Between '2017-11-14T23:30:00.000' AND '2018-01-13T23:30:00.000';
GO
DROP TABLE table1;
DROP TABLE table2;
Produces the query plan
Thom~
Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
Larnu.uk
April 13, 2019 at 11:17 am
Without the full structure, the execution plan and the statistics, it's hard to say. Is visitduration a calculated column or something like that? It might explain it (maybe). If you at least posted the plan, preferably the actual plan to include runtime metrics, it'd be easier to provide an answer. Are you using query store and plan forcing? Check the plan header properties for a Use Plan property.
If SQL Server is scanning an index, it will usually attempt to scan a smaller index, if that index can satisfy the query. Just what you've given us, it sounds really odd, but I don't think we have nearly enough information.
And NOLOCK... <sigh>.
"The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
- Theodore Roosevelt
Author of:
SQL Server Execution Plans
SQL Server Query Performance Tuning
April 13, 2019 at 1:30 pm
I understand. Let me arrange the plan and query. I can't add all the data as it is big enough but will see If I can reproduce it with minimum required.
Grant:
Are you using query store and plan forcing: NO
Is visitduration a calculated column or something like that? :NO
SQL Server is scanning an index, it will usually attempt to scan a smaller index: yes , this index has the smallest key width but it no way satisfies my query.
Will add more details by Monday
Online Trainer For SQL DBA and Developer @RedBushTechnologies with 18 yrs exp.
April 14, 2019 at 6:19 am
I understand. Let me arrange the plan and query. I can't add all the data as it is big enough but will see If I can reproduce it with minimum required. Grant: Are you using query store and plan forcing: NO Is visitduration a calculated column or something like that? :NO SQL Server is scanning an index, it will usually attempt to scan a smaller index: yes , this index has the smallest key width but it no way satisfies my query. Will add more details by Monday
I had a query that was scanning a small index as the plan had an implicit data type conversion on the primary key and it was faster to scan the smallest NC index to complete the conversion rather than the clustered index where the primary key was the clustering key. Eliminated the implicit conversion and the scan of the NC index went away.
April 14, 2019 at 3:54 pm
Hi I came across a scenario where a query is picking totally unrelated index in the execution plan. Here is the case: SELECT A.tranid,A.transittime FROM table1 A WITH(nolock) JOIN table2 B WITH(NOLOCK) On (A.tranid=B.TranId and A.ProdType=B.Prodtype ) WHERE A.transittime Between '2017-11-14 23:30:00.000' AND '2018-01-13 23:30:00.000' There are couple of indexes which are best suited for this query like : CREATE INDEX IDX1 ON table1(tranid,ProdType,transittime) CREATE INDEX IDX2 ON table2(tranid,ProdType ) But surprisingly, the query gets below index scan in plan: CREATE INDEX IDX3 ON table1(Visitduration ) this index column Visitduration is no where part of my query, but still optimizer scans it. Why index IDX1 seek in not happening here? What scenario might cause it? the query return around 200K records. If I use index hint to force the IDX1 use, then my performance gets slower compared to IDX3 use. Any thoughts?
Yes... obviously, the two indexes you created aren't up to the task of quickly isolating the data you wanted. The optimizer also decided (apparently) that your indexes weren't even worth being used in a scan. The optimizer is a "cost based" system and, to be quick, it doesn't necessarily try everything and will sometimes come up with a "good enough" plan. It's also heavily dependent on "statistics" and indexes (especially but not limited to Clustered Indexes) based on columns that have "ever-increasing" values, such as an IDENTITY column, can quickly go "out of date" because they quickly surpass what has been stored in "statistics". You do have to be diligent in maintaining "statistics" in such cases.
All that being said, I believe that your indexes are actually to blame and that the optimizer picked a different index to use as a more narrow version of what your table contains. Of course, that will result in an index scan unless the leading column is something that it can do a seek on. It cannot seek on other columns alone.
Not to be repetitive but your indexes aren't up to the task. I believe you will need the lead column of the index to start with the "transittime" column because the criteria in the WHERE clause is normally evaluated first to cut down on the number of joined rows that must be accomplished to satisfy the query.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply