Проблема производительности запросов SQL Server с нумерацией страниц ROW_NUMBER

#sql-server

#sql-сервер

Вопрос:

Не мог бы кто-нибудь из вас сообщить мне, почему функция подкачки row_number имеет проблемы с производительностью при использовании "HERE results.ROWNUMBER BETWEEN 1 AND 50 предложения (занимает более 2 минут), но запускается через 5 секунд, когда я комментирую предложение where, которое вернет весь результирующий набор, который возвращает около 623 записей.

Я вижу, что запрос использует одни и те же индексы, но некоторые, как при использовании предложения where, логические чтения экспоненциально увеличиваются для 2 таблиц, как показано ниже, я пытался исправить это довольно давно, любая помощь с благодарностью.

Спасибо

при использовании предложения where

Таблица ‘INTERCHANGEJDO’. Количество сканирований 15416, логическое чтение 144336865, физическое чтение 0, чтение с опережением 0, логическое чтение lob 0, физическое чтение lob 0, чтение с опережением lob 0.
Таблица «Рабочая таблица». Количество сканирований 16, логические чтения 70965478, физические чтения 0, чтение с опережением 0, lob логические чтения 0, lob физические чтения 0, lob чтение с опережением

Когда предложение where прокомментировано

Таблица ‘INTERCHANGEJDO’. Количество сканирований 16, логическое чтение 18501, физическое чтение 0, чтение с опережением 0, логическое чтение lob 0, физическое чтение lob 0, чтение с опережением lob 0.
Таблица «Рабочая таблица». Количество сканирований 0, логическое чтение 0, физическое чтение 0, чтение с опережением 0, логическое чтение lob 0, физическое чтение lob 0, чтение с опережением lob 0.

 SET STATISTICS IO ON
GO

WITH ALLRESULTS AS 
(
    SELECT 
        t5.*, ROW_NUMBER() OVER (ORDER BY FUNCTIONALGROUPNAME DESC) ROWNUMBER 
    FROM
        (SELECT 
             t0.JDOID, t0.ACCEPTCODE, t0.ACCEPTCODE824,t0.ACKDATE, t0.UTILITY, 
             t0.DIRECTION, t0.DOCUMENTREFERENCENUMBER, t3.DESCRIPTION FUNCTIONALGROUPNAME, 
             t0.INTERCHANGE_JDOID, t0.MODIFIEDBY, t0.MODIFYDATE, t0.PROCESSDATE, 
             t0.SENTDATE, t0.SETID, t0.STATUS, t0.TURNED,
             t0.PARTNER, t0.NETWORKID, t1.INTERCHANGECONTROLNUMBER, t1.TRADINGPARTNERPAIR_JDOID,
             TRANSLATIONJOBID = CASE 
                                   WHEN (t0.TRANSLATIONJOBID IS NULL OR t0.TRANSLATIONJOBID = '') 
                                      THEN t1.TRANSLATIONJOBID
                                      ELSE t0.TRANSLATIONJOBID 
                                END
         FROM  
             DOCUMENTJDO AS t0 WITH (NOLOCK) 
         INNER JOIN 
             INTERCHANGEJDO t1 ON t0.INTERCHANGE_JDOID = t1.JDOID
         INNER JOIN 
             TRADINGPARTNERPAIRJDO t3 ON t1.TRADINGPARTNERPAIR_JDOID = t3.JDOID 
         WHERE 
             t0.direction = 'I' 
             AND t0.processDate >= '2019-07-18 00:00:00'
             AND t0.processDate <= '2020-09-18 23:59:59' 
             AND (t1.TRADINGPARTNERPAIR_JDOID IN (SELECT DISTINCT vw.TPPDS_JDOID 
                                                  FROM vwEDXMain vw WITH (NOLOCK) 
                                                  WHERE (vw.levelCode LIKE '32,J4Q%') 
                                                    AND vw.TPPDS_JDOID IS NOT NULL))) AS t5
),
RESULT AS 
(
    SELECT 
        results.*, 
        (SELECT COUNT(*) FROM ALLRESULTS) AS TOTAL 
    FROM 
        ALLRESULTS AS results
    WHERE 
        results.ROWNUMBER BETWEEN 1 AND 50
),
DOCUMENTVIEWED AS 
(
    SELECT DISTINCT DOCUMENTID 
    FROM DOCUMENTUSERJDO WITH (NOLOCK) 
    WHERE VIEWED = 1
),
DOCUMENTVIEWEDBYUSER AS 
(
    SELECT DISTINCT DOCUMENTID AS DOCUMENTID_USER, USERID, VIEWED 
    FROM DOCUMENTUSERJDO
    WHERE USERID = 'com.-19422' AND VIEWED = 1
)
SELECT 
    t5.*,
    VIEWED = CASE 
                WHEN t5.DOCUMENTID_VIEWED IS NULL 
                   THEN 0 
                WHEN t6.USERID IS NULL 
                   THEN 2 
                ELSE T6.VIEWED 
             END
FROM 
    (SELECT 
         t3.*, 
         t4.DOCUMENTID AS DOCUMENTID_VIEWED 
     FROM 
         RESULT AS t3
     LEFT JOIN 
         DOCUMENTVIEWED AS t4 ON t4.DOCUMENTID = 'com.-'   ltrim(t3.JDOID)) AS t5
LEFT JOIN 
    DOCUMENTVIEWEDBYUSER AS t6 ON t6.DOCUMENTID_USER = t5.DOCUMENTID_VIEWED 
ORDER BY 
    T5.ROWNUMBER
GO

SET STATISTICS IO OFF
 

Комментарии:

1. Я настоятельно рекомендую узнать о пробелах и разрывах строк; что SQL невозможно прочитать. Тот факт, что псевдонимы не имеют смысла, тоже не помогает: вредные привычки: использование псевдонимов таблиц, таких как (a, b, c) или (t1, t2, t3) . Вам также нужны все эти NOLOCK подсказки (особенно в отношении одного объекта, который является VIEW ? Понимаете ли вы ее последствия? Вредные привычки: везде ставить NOLOCK

2. Я подозреваю, что существует проблема с вложенным циклом. Возможно, вы можете удалить все, кроме полей и таблиц, необходимых для получения требуемых записей. Я обнаружил, что иногда, сосредоточившись сначала на «ключах», легче эффективно получать только нужные записи. Уточнение по одному шагу за раз может показать, на каком этапе находится проблема. Этот запрос сложный. Оптимизатор пытается дать вам именно то, о чем вы просите, но, возможно, вы можете попросить то же самое менее сложным способом.