SQL-нумерация страниц очень медленная с несколькими левыми соединениями - PullRequest
0 голосов
/ 06 октября 2019

У меня есть хранимая процедура, на которой я должен использовать нумерацию страниц, чтобы получить записи для сетки. Запрос отлично работает для одной таблицы, однако, как только я начинаю добавлять в левое соединение, все становится все медленнее и медленнее. Простой запрос к странице 10 записей занимает 1 секунду с одной таблицей, но 3 минуты с 2 левыми соединениями. Все таблицы имеют индексы на них. Есть ли лучший, более эффективный способ написать это с помощью левых соединений? Возможно, подзапрос?

DECLARE 
    @Declare PersonNumber XML,
    @PageSize INT = 10, 
    @PageNum  INT = 1;

WITH TempResult AS
(
    SELECT ID, Name
    FROM Table T
    LEFT JOIN Table A ON a.Id = T.Id
    LEFT JOIN Table B ON B.Id = A.Id 
                      AND B.Date = A.DATE 
                      AND B.IsActive = 1
), TempCount AS 
(
    SELECT COUNT(*) AS MaxRows 
    FROM TempResult
)
SELECT *
FROM TempResult, TempCount
ORDER BY TempResult.Name
    OFFSET (@PageNum - 1) * @PageSize ROWS
    FETCH NEXT @PageSize ROWS ONLY

Нужные столбцы проиндексированы.

Ответы [ 2 ]

0 голосов
/ 06 октября 2019

Иногда запросы слишком сложны для того, чтобы механизм выполнялся наиболее оптимальным способом. Вы можете попытаться дать движку более простые запросы и лучшие советы, чтобы работать без сбоев.

Итак, в этом случае:

  1. Упростите запрос:

    CREATE TABLE #TempResult
    (
        [ID] INT
       ,[Name] NVARCHAR(128)
    );
    
    INSERT INTO #TempResult ([ID], Name])
    SELECT ID, Name
    FROM Table T
    LEFT JOIN Table A ON a.Id = T.Id
    LEFT JOIN Table B ON B.Id = A.Id 
                      AND B.Date = A.DATE 
                      AND B.IsActive = 1;
    
    DECLARE @MaxRows INT;
    
    SELECT @MaxRows = COUNT(*)
    FROM #TempResult;
    
    SELECT *
          ,@MaxRows AS [MaxRows]
    FROM #TempResult
    ORDER BY Name
    OFFSET (@PageNum - 1) * @PageSize ROWS
    FETCH NEXT @PageSize ROWS ONLY;
    
  2. Тогда, если начальный запрос с LEFT JOIN медленный, попытайтесь оптимизировать его. Например, вы можете добавить проверку, какие индексы используются для извлечения данных (если такие существуют) - вы можете добавить индекс фильтра для оптимизации запроса.

  3. Если извлечены другие столбцы и возвращены -например, имя, почта, адрес или другой материал, не извлекайте их. Получите только ID s и столбец, по которому вы заказываете. Выполните пейджинг и с результатом ID s получите другие детали.
0 голосов
/ 06 октября 2019

Чтобы быть эффективным, запрос OFFSET ... FETCH должен соответствовать следующим правилам:

  1. Столбцы ORDER BY должны быть уникальными и иметь индекс
  2. Нет общего количества строк. Это всегда дорого.
  3. Запрос должен найти целевые строки перед выполнением множества других логических операций, таких как объединения.

Без таблицы и индекса DDL и фактического запросаВ планах трудно быть более точным.

...