Лучшее решение возможно, если есть уникальный индекс в таблице Person.Person (например, есть уникальный индекс в столбце PersonID
, и этот индекс кластеризуется - например, если у вас есть кластерный ПК). В таких случаях выше запроса можно переписать следующим образом:
;WITH tmp_cte AS (
SELECT ROW_NUMBER() OVER (ORDER BY LastName) AS RowNumber, PersonID
FROM person.Person
WHERE FirstName like '%ad%'
)
SELECT ...
FROM Person.Person p
WHERE p.PersonID IN -- PersonID is the key of this UNIQUE INDEX
(
SELECT PersonID FROM tmp_cte
WHERE RowNumber > @skip 10 AND RowNumber <= @Take--20
)
или
DECLARE @Rows TABLE (ID INT PRIMARY KEY);
;WITH tmp_cte AS (
SELECT ROW_NUMBER() OVER (ORDER BY LastName) AS RowNumber, PersonID
FROM person.Person
WHERE FirstName like '%ad%'
)
INSERT @Rows (ID)
SELECT PersonID FROM tmp_cte
WHERE RowNumber > @skip 10 AND RowNumber <= @Take--20
SELECT ...
FROM Person.Person p
WHERE p.PersonID IN (SELECT ID FROM @Rows); -- PersonID is the key of this UNIQUE INDEX
Примечание # 1: В данном конкретном случае, индекс по (FirstName, LastName)
или (LastName, FirstName)
может быть также полезно.
Примечание № 2: Это решение должно работать лучше, если в окончательном SELECT
должно быть больше столбцов.
Основная проблема с производительностью будет состоять в следующем: 'FirstName like '% ad%'' и, во-вторых, разбиение на страницы (что будет проблемой с большими смещениями и если в общем случае будет много строк, соответствующих указанному выше первому условию.) –
@ypercube: Не согласен. Основная проблема заключается в том, что это решение и решение с наибольшим числом. голосов недостаточно. Эти решения требуют больших индексов, а при большом числе страниц (в конце «ORDER BY LastName») производительность ухудшается. –