Powiedzmy, że mam jeden stolik
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
);
W tym przykładzie TicketId
jest klucz podstawowy.
Chcę, aby użytkownicy mogli tworzyć zapytania „częściowo ad-hoc” dla tej tabeli. Mówię częściowo, ponieważ kilka części zapytania zawsze zostanie naprawionych:
- Zapytanie zawsze wykona filtr zakresu na
InsertDateTime
- Zapytanie będzie zawsze
ORDER BY InsertDateTime DESC
- Zapytanie wyświetli wyniki strony
Użytkownik może opcjonalnie filtrować według dowolnej innej kolumny. Mogą filtrować według żadnego, jednego lub wielu. I dla każdej kolumny użytkownik może wybrać z zestawu wartości, które zostaną zastosowane jako rozłączenie. Na przykład:
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;
Załóżmy teraz, że tabela ma 100 000 000 wierszy.
Najlepsze, co mogę wymyślić, to indeks obejmujący każdą z „opcjonalnych” kolumn:
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
To daje mi plan zapytań w następujący sposób:
- WYBIERZ
- Filtr
- Top
- Sequence Project (Compute Scalar)
- Człon
- Indeks Szukaj
- Człon
- Sequence Project (Compute Scalar)
- Top
- Filtr
Wygląda całkiem nieźle. Około 80% -90% kosztów pochodzi z operacji indeksowania, która jest idealna.
Czy istnieją lepsze strategie wdrażania tego rodzaju wyszukiwania?
Niekoniecznie chcę odciążyć opcjonalne filtrowanie do klienta, ponieważ w niektórych przypadkach zestaw wyników z części „ustalonej” może wynosić 100s lub 1000s. Klient byłby wówczas także odpowiedzialny za sortowanie i stronicowanie, które może zbyt wiele dla niego działać.
RowNum BETWEEN 101 AND 200
?