Digamos que tengo una sola mesa
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
);
En este ejemplo TicketId
es la clave primaria.
Quiero que los usuarios puedan crear consultas "parcialmente ad-hoc" en esta tabla. Digo parcialmente porque algunas partes de la consulta siempre se solucionarán:
- La consulta siempre realizará un filtro de rango en un
InsertDateTime
- La consulta siempre
ORDER BY InsertDateTime DESC
- La consulta buscará resultados
El usuario puede filtrar opcionalmente en cualquiera de las otras columnas. Pueden filtrar en ninguno, uno o muchos. Y para cada columna, el usuario puede seleccionar entre un conjunto de valores que se aplicarán como una disyunción. Por ejemplo:
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;
Ahora suponga que la tabla tiene 100,000,000 filas.
Lo mejor que se me ocurre es un índice de cobertura que incluye cada una de las columnas "opcionales":
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Esto me da un plan de consulta de la siguiente manera:
- SELECCIONE
- Filtrar
- Parte superior
- Proyecto de secuencia (calcular escalar)
- Segmento
- Búsqueda de índice
- Segmento
- Proyecto de secuencia (calcular escalar)
- Parte superior
- Filtrar
Parece bastante bueno Alrededor del 80% -90% del costo proviene de la operación Index Seek, que es ideal.
¿Existen mejores estrategias para implementar este tipo de búsqueda?
No necesariamente quiero descargar el filtrado opcional al cliente porque en algunos casos el conjunto de resultados de la parte "fija" podría ser 100 o 1000. El cliente también sería responsable de la clasificación y paginación, lo que podría funcionar demasiado para el cliente.
RowNum BETWEEN 101 AND 200
?