Допустим, у меня есть одна таблица
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
?Ответы:
Если эта конкретная рабочая нагрузка составляет большинство запросов к таблице, вы можете рассмотреть следующее:
Соображения:
Преимущества:
источник
Я использовал эту технику в прошлом. Таблица была не такой большой, но критерии поиска были более сложными.
Это короткая версия.
источник
Учитывая ваши первые два условия, я бы посмотрел на кластерный индекс
InsertDateTime
.источник
почему вы не рассматриваете разделение? Он доступен в SQL 2008 и более поздних версиях, но требует редакции Enterprise (или редакции для разработчиков).
По сути, вы разбили свою таблицу на несколько разделов и определили критерии (функции) для вашего диапазона дат?
https://www.simple-talk.com/sql/database-administration/gail-shaws-sql-server-howlers/
источник
Если клиенты фильтруют почти одинаково снова и снова, вы можете создать индекс для этих запросов.
Например, клиент фильтрует по SiteId и StatusId, вы можете создать дополнительный индекс:
Таким образом, большинство «более распространенных» запросов могут выполняться быстро.
источник