I have a table with 5 million records as follows
Id BasePrefix DestPrefix ExchangeSetId ClassId
11643987 0257016 57016 1 3
11643988 0257016 57278 1 3
11643989 0257016 57279 1 3
11643990 0257016 57751 1 3
SQL Tuning adviser recomended the following index
CREATE NONCLUSTERED INDEX [ExchangeIdx] ON [dbo].[Exchanges]
(
[ExchangeSetId] ASC,
[BasePrefix] ASC,
[DestPrefix] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
However given the following
DECLARE @exchangeSetID int = 1;
DECLARE @BasePrefix nvarchar( 10 ) = '0732056456';
DECLARE @DestPrefix nvarchar( 10 ) = '30336456';
DECLARE @BaseLeft nvarchar( 10 ) = left(@BasePrefix,4);
These 2 queries give me vastly different execution plans
Query 1
SELECT TOP 1 ClassId
FROM Exchanges
WHERE
exchangeSetID = @exchangeSetID
AND BasePrefix LIKE '0732' + '%'
AND '0732056456' LIKE BasePrefix + '%'
AND '30336456' LIKE DestPrefix + '%';
SELECT TOP 1 ClassId
FROM Exchanges
WHERE
exchangeSetID = @exchangeSetID
AND BasePrefix LIKE @BaseLeft + '%'
AND @BasePrefix LIKE BasePrefix + '%'
AND @DestPrefix LIKE DestPrefix + '%';
The difference between the 2 queries are @BaseLeft
and '0732'
respectively
Basically, in the first example the index is used, and in the second, not so much
Is there any compelling reason why this should be so?
And if this is not just a fundamental flaw in my thinking, how could i pass a variable to the second query and make use of the index?
The following recommendations will help you in your SQL tuning process.
You'll find 3 sections below:
CREATE INDEX exchanges_idx_exchangesetid ON Exchanges (exchangeSetID);
SELECT
TOP 1 Exchanges.ClassId
FROM
Exchanges
WHERE
Exchanges.exchangeSetID = @exchangeSetID
AND Exchanges.BasePrefix LIKE '0732' + '%'
AND '0732056456' LIKE Exchanges.BasePrefix + '%'
AND '30336456' LIKE Exchanges.DestPrefix + '%'