Это легко воспроизвести.
Просто вставьте следующие фиктивные данные в таблицу в вашем вопросе ...
insert into [dbo].[table]
SELECT TOP 1000000 DATEADD(SECOND, CRYPT_GEN_RANDOM(4)% 1000000,GETDATE()) , 1, 1, 1, 1
FROM sys.all_objects o1, sys.all_objects o2
Затем выполните
DECLARE @date datetime2(2) = '2018.07.10'
DECLARE @date2 datetime2(2) = '2018.08.10'
SELECT TOP 10 npl.NPId
FROM [table] npl
WHERE npl.RequestDate >= @date
AND npl.RequestDate < @date2
ORDER BY npid
OPTION (QUERYTRACEON 9130) /*so filter visible in the plan*/
SELECT TOP 10 npl.NPId
FROM [table] npl WITH (INDEX = IX_ReqDate)
WHERE npl.RequestDate >= @date
AND npl.RequestDate < @date2
ORDER BY npid
Выше используется CardinalityEstimationModelVersion = 140
- подобное будет видно в других версиях CE, хотя точные числа могут отличаться.
- Значения, используемые в диапазоне данных, скрытыв переменных, поэтому SQL Server предполагает, что он будет соответствовать
16.431676725155%
строкам (0.30*SQRT(0.30)
). - SQL Server также предполагает, что эти строки будут равномерно распределены по всей таблице.Таким образом, он предполагает, что ему нужно прочитать 60,8581 (
10/(0.30*SQRT(0.30))
), прежде чем он получит 10, соответствующих предикату. - Для другого плана он предполагает, что ему нужно отсортировать 16,4% таблицы, которая стоит значительно дороже.
Вы можете попробовать добавить OPTION (RECOMPILE)
, чтобы SQL Server анализировал диапазон дат, используемый переменной, и может уменьшить оценку на 16,4% настолько, чтобы изменить план.
Однако, вероятно, более вероятно, что оценки уменьшены, но не настолько, чтобы изменить план, а план КИ по-прежнему недоработан (поскольку строки, соответствующие диапазону, не распределены равномерно по всей таблице, и должно быть гораздо больше строк).прочитайте, чем оценили).В этом случае вы можете рассмотреть возможность использования подсказки индекса, чтобы он выбрал нужный индекс.