나는 이와 같은 테이블을 가지고있다 :
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
증가하는 ID로 객체에 대한 업데이트를 필수적으로 추적합니다.
이 테이블의 소비자 UpdateId
는 특정 순서대로 시작하여 100 개의 고유 한 개체 ID 청크를 선택합니다 UpdateId
. 기본적으로 중단 된 위치를 추적 한 다음 업데이트를 쿼리합니다.
난 단지 쿼리를 작성하여 최대로 최적의 쿼리 계획을 생성 할 수있었습니다 때문에 나는 흥미로운 최적화 문제가이 찾은 일이 나는 인덱스로 인해 원하지만하지 않는 것을 할 보장 내가 원하는 무엇을 :
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
@fromUpdateId
저장 프로 시저 매개 변수는 어디에 있습니까 ?
계획 :
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
UpdateId
사용중인 인덱스 에 대한 검색으로 인해 결과는 이미 좋으며 원하는대로 가장 낮은 업데이트 ID에서 가장 높은 업데이트 ID로 정렬됩니다. 그리고 이것은 흐름 별개의 계획을 생성합니다 . 그러나 순서는 분명히 동작이 보장되지 않으므로 사용하고 싶지 않습니다.
이 트릭은 또한 동일한 쿼리 계획을 만듭니다 (중복 TOP이 있음에도 불구하고).
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
그럼에도 불구하고 이것이 정말로 주문을 보장하는지 확실하지 않습니다.
SQL Server가 단순화하기에 충분히 영리하기를 바랐던 하나의 쿼리는 이것이지만 매우 잘못된 쿼리 계획을 생성하게됩니다.
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
계획 :
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
인덱스 검색을 사용 UpdateId
하고 중복을 제거 하는 고유 한 흐름으로 최적의 계획을 생성하는 방법을 찾으려고합니다 ObjectId
. 어떤 아이디어?
원하는 경우 샘플 데이터 . 객체는 하나 이상의 업데이트를 거의하지 않으며 100 행 세트 내에 하나 이상을 가져서는 안됩니다. 그래서 내가 알지 못하는 것이 없다면 흐름이 뚜렷 하지 않습니다. 그러나 ObjectId
테이블에 단일 행이 100 개를 초과하지 않는다는 보장은 없습니다 . 이 테이블에는 1,000,000 개가 넘는 행이 있으며 빠르게 성장할 것으로 예상됩니다.
이것의 사용자가 적절한 다음을 찾을 수있는 다른 방법이 있다고 가정합니다 @fromUpdateId
. 이 쿼리에서 반환 할 필요가 없습니다.