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.
fuente
RowNum BETWEEN 101 AND 200
?Respuestas:
Si esta carga de trabajo en particular es la mayoría de las consultas en la tabla, puede considerar:
Consideraciones:
Ventajas:
fuente
He usado esta técnica en el pasado. La tabla no era tan grande, pero el criterio de búsqueda era más complejo.
Esta es la version corta.
fuente
Dadas sus dos primeras condiciones previas, estaría mirando un índice agrupado
InsertDateTime
.fuente
¿Por qué no consideras la partición? Está disponible en SQL 2008 en adelante, pero requiere la edición Enterprise (o la edición Developer).
Básicamente, divide su tabla en varias particiones y define sus criterios de partición (función) ¿sería su rango de fechas?
https://www.simple-talk.com/sql/database-administration/gail-shaws-sql-server-howlers/
fuente
Si los clientes están filtrando casi de la misma manera una y otra vez, puede crear un índice para esas consultas.
Por ejemplo, el cliente está filtrando en SiteId y StatusId, puede crear un índice adicional:
De esta manera, la mayoría de las consultas 'más comunes' podrían ejecutarse rápidamente.
fuente