문제의 예제는 동일한 결과를 얻지 못합니다 (이 OFFSET
예제에는 오류가 있습니다). 아래의 업데이트 된 양식은 해당 문제를 해결하고 ROW_NUMBER
사례에 대한 추가 정렬을 제거하고 변수를 사용하여 솔루션을보다 일반적으로 만듭니다.
DECLARE
@PageSize bigint = 10,
@PageNumber integer = 3;
WITH Numbered AS
(
SELECT TOP ((@PageNumber + 1) * @PageSize)
o.*,
rn = ROW_NUMBER() OVER (
ORDER BY o.[object_id])
FROM #objects AS o
ORDER BY
o.[object_id]
)
SELECT
x.name,
x.[object_id],
x.principal_id,
x.[schema_id],
x.parent_object_id,
x.[type],
x.type_desc,
x.create_date,
x.modify_date,
x.is_ms_shipped,
x.is_published,
x.is_schema_published
FROM Numbered AS x
WHERE
x.rn >= @PageNumber * @PageSize
AND x.rn < ((@PageNumber + 1) * @PageSize)
ORDER BY
x.[object_id];
SELECT
o.name,
o.[object_id],
o.principal_id,
o.[schema_id],
o.parent_object_id,
o.[type],
o.type_desc,
o.create_date,
o.modify_date,
o.is_ms_shipped,
o.is_published,
o.is_schema_published
FROM #objects AS o
ORDER BY
o.[object_id]
OFFSET @PageNumber * @PageSize - 1 ROWS
FETCH NEXT @PageSize ROWS ONLY;
ROW_NUMBER
계획의 예상 비용이 0.0197935를 :
OFFSET
계획의 예상 비용이 0.0196955를 :
즉, 0.000098 예상 비용 단위를 절약 OFFSET
할 수 있습니다 (각 행에 대해 행 번호를 리턴하려는 경우 계획에 추가 연산자가 필요함). OFFSET
계획은 여전히, 일반적으로 약간 저렴하지만, 예상 비용은 정확히 것을 기억하고 - 실제 시험이 여전히 필요합니다. 두 계획에서 비용의 대부분은 모든 종류의 입력 집합 비용이므로 유용한 인덱스는 두 솔루션 모두에 도움이됩니다.
상수 리터럴 값이 사용되는 경우 (예 : OFFSET 30
원래 예에서) 옵티마이 저는 전체 정렬 대신 TopN 정렬을 사용하고 그 뒤에 Top을 사용할 수 있습니다. TopN 정렬에서 필요한 행이 상수 리터럴이고 <= 100 ( OFFSET
및 의 합 FETCH
) 인 경우 실행 엔진은 일반화 된 TopN 정렬보다 빠르게 수행 할 수 있는 다른 정렬 알고리즘 을 사용할 수 있습니다. 세 가지 경우 모두 전체적으로 성능 특성이 다릅니다.
옵티마이 ROW_NUMBER
저가 구문 패턴을 자동으로 변환하지 않는 OFFSET
이유는 여러 가지 이유가 있습니다.
- 기존의 모든 용도와 일치하는 변환을 작성하는 것은 거의 불가능합니다.
- 일부 페이징 쿼리가 자동으로 변환되고 다른 것은 아닌 것이 혼동 될 수 있습니다.
OFFSET
계획은 모든 경우에 더 나은 보장 할 수 없습니다
페이징 세트가 상당히 넓은 위의 세 번째 포인트에 대한 한 가지 예가 발생합니다. 비 클러스터형 인덱스를 사용하여 필요한 키 를 찾고OFFSET
또는로 인덱스를 스캔하는 것과 비교하여 클러스터형 인덱스를 수동으로 조회하는 것이 훨씬 더 효율적일 수 있습니다 ROW_NUMBER
. 있습니다 고려해야 할 추가 문제 페이징 응용 프로그램 전체에서 얼마나 많은 행 또는 페이지 알아야 할 필요가있는 경우는. 'key seek'및 'offset'방법의 상대적인 장점에 대한 또 다른 좋은 논의가 있습니다 .
전반적으로 사람들은 OFFSET
적절한 테스트를 거친 후 적절한 경우 사용하도록 페이징 쿼리를 변경하기위한 정보에 근거한 결정을 내리는 것이 좋습니다 .