Digamos que eu tenho uma única tabela
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
);
Neste exemplo TicketId
é a chave primária.
Desejo que os usuários possam criar consultas "parcialmente ad-hoc" nessa tabela. Eu digo parcialmente porque algumas partes da consulta sempre serão corrigidas:
- A consulta sempre executará um filtro de intervalo em um
InsertDateTime
- A consulta sempre
ORDER BY InsertDateTime DESC
- A consulta paginará os resultados
O usuário pode opcionalmente filtrar em qualquer uma das outras colunas. Eles podem filtrar nenhum, um ou muitos. E para cada coluna, o usuário pode selecionar um conjunto de valores que serão aplicados como uma disjunção. Por exemplo:
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;
Agora suponha que a tabela tenha 100.000.000 de linhas.
O melhor que posso apresentar é um índice de cobertura que inclua cada uma das colunas "opcionais":
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Isso me dá um plano de consulta da seguinte maneira:
- SELECT
- Filtro
- Topo
- Projeto de sequência (escalar computacional)
- Segmento
- Busca de índice
- Segmento
- Projeto de sequência (escalar computacional)
- Topo
- Filtro
Parece muito bom. Cerca de 80% a 90% do custo vem da operação Index Seek, o que é ideal.
Existem melhores estratégias para implementar esse tipo de pesquisa?
Não quero necessariamente descarregar a filtragem opcional para o cliente porque, em alguns casos, o conjunto de resultados da parte "fixa" pode ser 100s ou 1000s. O cliente também seria responsável pela classificação e paginação, o que pode funcionar muito para o cliente.
RowNum BETWEEN 101 AND 200
?