Допустим, у меня есть одна таблица
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
);
Это дает мне план запроса следующим образом:
- ВЫБРАТЬ
- Фильтр
- верхний
- Sequence Project (вычислить скаляр)
- сегмент
- Поиск индекса
- сегмент
- Sequence Project (вычислить скаляр)
- верхний
- Фильтр
Это выглядит довольно хорошо. Около 80% -90% затрат приходится на операцию поиска индекса, которая является идеальной.
Есть ли лучшие стратегии для реализации такого поиска?
Я не хочу разгрузить дополнительную фильтрацию на клиенте, потому что в некоторых случаях набор результатов из «фиксированной» части может быть 100 или 1000 с. Клиент также будет отвечать за сортировку и разбиение по страницам, что может быть слишком много для клиента.
RowNum BETWEEN 101 AND 200?