Disons que j'ai une seule table
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
);
Dans cet exemple, TicketId
la clé primaire.
Je souhaite que les utilisateurs puissent créer des requêtes "partiellement ad hoc" sur cette table. Je dis en partie parce que certaines parties de la requête seront toujours corrigées:
- La requête effectuera toujours un filtre de plage sur un
InsertDateTime
- La requête sera toujours
ORDER BY InsertDateTime DESC
- La requête affichera les résultats
L'utilisateur peut éventuellement filtrer sur n'importe quelle autre colonne. Ils peuvent filtrer sur aucun, un ou plusieurs. Et pour chaque colonne, l'utilisateur peut choisir parmi un ensemble de valeurs qui seront appliquées comme une disjonction. Par exemple:
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;
Supposons maintenant que la table comporte 100 000 000 lignes.
Le mieux que je puisse trouver est un index de couverture qui inclut chacune des colonnes "facultatives":
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Cela me donne un plan de requête comme suit:
- SÉLECTIONNER
- Filtre
- Haut
- Projet de séquence (calcul scalaire)
- Segment
- Recherche d'index
- Segment
- Projet de séquence (calcul scalaire)
- Haut
- Filtre
Cela semble plutôt bien. Environ 80% à 90% du coût provient de l'opération Index Seek, ce qui est idéal.
Existe-t-il de meilleures stratégies pour mettre en œuvre ce type de recherche?
Je ne veux pas nécessairement décharger le filtrage optionnel sur le client car dans certains cas, le jeu de résultats de la partie "fixe" peut être de 100 ou de 1000. Le client serait alors également responsable du tri et de la pagination, ce qui pourrait trop fonctionner pour le client.
RowNum BETWEEN 101 AND 200
?