Некластеризованный индекс SQL Server 2016 не используется при упорядочении по индексу кластеризации - PullRequest
1 голос
/ 23 апреля 2019

Не могли бы вы объяснить, почему этот некластерный индекс не используется при запросах вместе с упорядочением по кластерному индексу?

CREATE TABLE [dbo].[table]
(
    [NPId] [BIGINT] IDENTITY(1,1) NOT NULL, 
    [RequestDate] [DATETIME2](2) NOT NULL,
    [Status] [TINYINT] NOT NULL,
    [StatusCodeId] [SMALLINT] NULL,
    [NumberCount] [INT] NULL,
    [Number] [BIGINT] NULL,

    CONSTRAINT [PK_NPLog_1] 
       PRIMARY KEY CLUSTERED ([NPId] ASC)
               WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                     IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                     ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IX_ReqDate] 
ON [dbo].[table] ([RequestDate] ASC)
INCLUDE ([NPId])

Запрос:

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

Если я установлю порядокпо requestDate тогда используется индекс.

1 Ответ

1 голос
/ 23 апреля 2019

Это легко воспроизвести.

Просто вставьте следующие фиктивные данные в таблицу в вашем вопросе ...

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

enter image description here

Выше используется CardinalityEstimationModelVersion = 140 - подобное будет видно в других версиях CE, хотя точные числа могут отличаться.

  1. Значения, используемые в диапазоне данных, скрытыв переменных, поэтому SQL Server предполагает, что он будет соответствовать 16.431676725155% строкам (0.30*SQRT(0.30)).
  2. SQL Server также предполагает, что эти строки будут равномерно распределены по всей таблице.Таким образом, он предполагает, что ему нужно прочитать 60,8581 (10/(0.30*SQRT(0.30))), прежде чем он получит 10, соответствующих предикату.
  3. Для другого плана он предполагает, что ему нужно отсортировать 16,4% таблицы, которая стоит значительно дороже.

Вы можете попробовать добавить OPTION (RECOMPILE), чтобы SQL Server анализировал диапазон дат, используемый переменной, и может уменьшить оценку на 16,4% настолько, чтобы изменить план.

Однако, вероятно, более вероятно, что оценки уменьшены, но не настолько, чтобы изменить план, а план КИ по-прежнему недоработан (поскольку строки, соответствующие диапазону, не распределены равномерно по всей таблице, и должно быть гораздо больше строк).прочитайте, чем оценили).В этом случае вы можете рассмотреть возможность использования подсказки индекса, чтобы он выбрал нужный индекс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...