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.
fonte
RowNum BETWEEN 101 AND 200
?Respostas:
Se essa carga de trabalho específica for a maioria das consultas na tabela, você poderá considerar:
Considerações:
Vantagens:
fonte
Eu usei essa técnica no passado. A tabela não era tão grande, mas o critério de pesquisa era mais complexo.
Esta é a versão curta.
fonte
Dadas as suas duas primeiras condições prévias, eu examinaria um índice em cluster
InsertDateTime
.fonte
por que você não considera o particionamento? Está disponível no SQL 2008 para cima, mas requer a edição Enterprise (ou Developer).
Basicamente, você divide sua tabela em várias partições e define seus critérios de partição (função).
https://www.simple-talk.com/sql/database-administration/gail-shaws-sql-server-howlers/
fonte
Se os clientes estiverem filtrando quase da mesma maneira repetidamente, você poderá criar um índice para essas consultas.
Por exemplo, o cliente está filtrando no SiteId e StatusId, você pode criar um índice adicional:
Dessa forma, a maioria das consultas 'mais comuns' pode ser executada rapidamente.
fonte