Почему «Пропустить» и «Взять» занимает больше времени, когда извлекаемая запись становится все больше и больше? - PullRequest
0 голосов
/ 22 февраля 2019

В таблице больше 50,000 records.Я использую Microsoft SQL Server 2016 (RTM-GDR).

Я использовал код для получения 200 записей одновременно.Приведенный ниже код работает нормально до 1000 записей, но после этого он занимает больше времени.

Код

int skip = 0; //Initially and gets increased by 200 for each calls (0, 200, 400, so on)
int take = 200; //Initially and remains same since only 200 records needed at a time.

var recordList = context.Records.OrderBy(x => x.IncentiveOUID)
                                .Skip(skip)
                                .Take(take)
                                .ToList();

Сгенерированный код SQL

SELECT TOP (200)
   [Extent1].[IncentiveOUID] AS [IncentiveOUID],
   [Extent1].[IncentiveID] AS [IncentiveID],
   [Extent1].[OrganizationUnitID] AS [OrganizationUnitID],
   [Extent1].[ModifiedDate] AS [ModifiedDate],
   [Extent1].[ModifiedBy] AS [ModifiedBy],
   [Extent1].[Id] AS [Id]
   FROM ( SELECT [Extent1].[IncentiveOUID] AS [IncentiveOUID], [Extent1].[IncentiveID] 
   AS [IncentiveID], [Extent1].[OrganizationUnitID] 
   AS [OrganizationUnitID], [Extent1].[ModifiedDate] 
   AS [ModifiedDate], [Extent1].[ModifiedBy] 
   AS [ModifiedBy], [Extent1].[Id] 
   AS [Id], row_number() OVER (ORDER BY [Extent1].[IncentiveOUID] ASC) AS [row_number]
       FROM [dbo].[cms_IncentiveOUs] AS [Extent1]
   )  AS [Extent1]
   WHERE [Extent1].[row_number] > 2400
   ORDER BY [Extent1].[IncentiveOUID] ASC

Готов предоставить больше информации, если это необходимо для объяснения вышеупомянутых материалов.

1 Ответ

0 голосов
/ 22 февраля 2019

SQL не имеет эффективного способа Skip: он должен прочитать все предыдущие строки.Вы выполняете сканирование индекса каждый раз, когда выбираете страницу записей, при этом каждая страница сканирует все больше и больше индекса.

Вместо того, чтобы разбивать на страницы результаты, рассмотрите возможность их выборки со смещением.Что-то вроде:

IEnumerable<Record> GetNext(int fromId = 0, int take = 50) => context.Records
    .Where(x => x.Id > fromId)
    .OrderBy(x => x.Id)
    .Take(take)
    .ToList();

Что с индексом на Id приведет к максимально эффективному поиску индекса.

...