ROW_NUMBER () OVER работает медленно с ORDER BY в одном столбце - PullRequest
0 голосов
/ 16 мая 2019

Я столкнулся с чем-то неожиданным в SQL Server 2012.

Пытаясь реализовать разбиение на страницы для унаследованного API, я обнаружил, что ROW_NUMBER() OVER с одним столбцом ORDER BY довольно медленно работает с большим набором данных.

Я должен предварить это, сказав, что у меня нет доступа к планам выполнения или статистике индекса.

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

SELECT 
    a.Erp_PK 
FROM
    (SELECT 
         ROW_NUMBER() OVER(ORDER by Erp_RowGUID asc) AS Row#, 
         Erp_PK 
     FROM 
         Erp 
     JOIN 
         Emp ON Emp_PK = Erp_EmpFK 
     WHERE 
         Emp_CompanyFK = 2611) a 
WHERE 
    Row# BETWEEN 399001 AND 400000

Таблица Erp содержит более 32 000 000 записей, а внутреннее предложение where возвращает более 440 000.

Я не знаю, почему человек, создавший API, решил заказать по GUID, но этот столбец имеет неуникальный некластеризованный индекс.

Вышеуказанный запрос выполняется примерно через 30 секунд.

Попробовав несколько вещей, я обнаружил, что добавление Erp_LastModified (также с неуникальным некластеризованным индексом) в качестве вторичной сортировки сокращает время запроса до 1 секунды.

Время запроса увеличилось до 30 секунд с одним ORDER BY из Erp_LastModified. Затем вернитесь к 2 секундам с помощью CAST (Exp_RowGUID as VARCHAR(100)).

Я ищу не столько решение, сколько какое-то представление о том, что здесь происходит.

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

Спасибо.

Ответы [ 3 ]

2 голосов
/ 16 мая 2019

Вместо этого вы можете попробовать использовать OFFSET, в противном случае, если это не улучшится, включите план выполнения вашего запроса вместе с DDL ваших таблиц с индексами:

SELECT Erp_PK
FROM Erp 
     JOIN Emp ON Emp_PK = Erp_EmpFK 
WHERE Emp_CompanyFK = 2611
ORDER BY Erp_RowGUID ASC
OFFSET 399000 ROWS FETCH NEXT 999 ROWS ONLY;

К сожалению, если мы не знаем DDL для объекта (ов) и не имеем доступа к плану выполнения, мы не сможем предложить намного больше. Кроме того, тот факт, что любые исправления могут потребовать изменений, которые вы не можете сделать, означает, что любые удары в темноте не могут быть проверены (и я бы советовал против этого в производственной системе).

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

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

0 голосов
/ 16 мая 2019

Согласно одной теории, ваш второй столбец в порядке упорядочения (тот, который повышает производительность) включается в индекс со столбцом emp_pk. Вы можете проверить это, упорядочив только по этому столбцу и посмотрев, занимает ли запрос 2 секунды (в индексе для сортировки используется первичный ключ) или потребуется 30 секунд (для генерации упорядочения выполняется полное сканирование всех строк). ).

0 голосов
/ 16 мая 2019

Вы пытались изменить запрос, чтобы использовать разбивку над предложением Order By?

SELECT Erp_PK 
FROM Erp 
    JOIN Emp ON Emp_PK = Erp_EmpFK 
WHERE Emp_CompanyFK = 2611
Order by a.Erp_PK 
    OFFSET (399000) ROWS FETCH NEXT (1000) ROWS ONLY 

OFFSET значения могут быть параметрами курса

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