하나의 테이블이 있다고 가정 해 봅시다.
CREATE TABLE Ticket (
TicketId int NOT NULL,
InsertDateTime datetime NOT NULL,
SiteId int NOT NULL,
StatusId tinyint NOT NULL,
AssignedId int NULL,
ReportedById int NOT NULL,
CategoryId int NULL
);
이 예 TicketId
에서는 기본 키입니다.
사용자가이 테이블에 대해 "부분적으로 임시"쿼리를 만들 수 있기를 바랍니다. 쿼리의 일부가 항상 고정되기 때문에 부분적으로 말합니다.
- 쿼리는 것입니다 항상 온 다양한 필터를 수행
InsertDateTime
- 쿼리는 항상
ORDER BY InsertDateTime DESC
- 쿼리 결과가 페이지에 표시됩니다
사용자는 다른 열을 선택적으로 필터링 할 수 있습니다. 그들은 하나, 또는 여러 개를 필터링 할 수 있습니다. 그리고 각 열에 대해 사용자는 분리로 적용될 일련의 값 중에서 선택할 수 있습니다. 예를 들면 다음과 같습니다.
SELECT
TicketId
FROM (
SELECT
TicketId,
ROW_NUMBER() OVER(ORDER BY InsertDateTime DESC) as RowNum
FROM Ticket
WHERE InsertDateTime >= '2013-01-01' AND InsertDateTime < '2013-02-01'
AND StatusId IN (1,2,3)
AND (CategoryId IN (10,11) OR CategoryId IS NULL)
) _
WHERE RowNum BETWEEN 1 AND 100;
이제 테이블에 100,000,000 개의 행이 있다고 가정하십시오.
내가 얻을 수있는 최선의 방법은 각각의 "선택적"열을 포함하는 포함 인덱스입니다.
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
이것은 다음과 같은 쿼리 계획을 제공합니다.
- 고르다
- 필터
- 상단
- 시퀀스 프로젝트 (컴퓨 트 스칼라)
- 분절
- 색인 찾기
- 분절
- 시퀀스 프로젝트 (컴퓨 트 스칼라)
- 상단
- 필터
꽤 좋아 보인다. 비용의 약 80 % -90 %는 Index Seek 작업에서 발생하며 이는 이상적입니다.
이런 종류의 검색을 구현하기위한 더 나은 전략이 있습니까?
경우에 따라 "고정 된"부분의 결과 세트가 100 또는 1000 일 수 있기 때문에 선택적 필터링을 클라이언트에 오프로드하지 않아도됩니다. 그런 다음 클라이언트는 정렬 및 페이징을 담당하여 클라이언트에게 너무 많은 작업을 수행 할 수도 있습니다.
RowNum BETWEEN 101 AND 200
?