Nehmen wir an, ich habe einen einzigen Tisch
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
);
In diesem Beispiel TicketId
ist der Primärschlüssel.
Ich möchte, dass Benutzer "teilweise Ad-hoc" -Abfragen für diese Tabelle erstellen können. Ich sage teilweise, weil einige Teile der Abfrage immer behoben werden:
- Die Abfrage führt immer einen Bereichsfilter für einen aus
InsertDateTime
- Die Abfrage wird immer
ORDER BY InsertDateTime DESC
- Die Abfrage zeigt die Ergebnisse an
Der Benutzer kann optional nach einer der anderen Spalten filtern. Sie können nach keiner, einer oder mehreren filtern. Und für jede Spalte kann der Benutzer aus einer Reihe von Werten auswählen, die als Disjunktion angewendet werden. Zum Beispiel:
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;
Angenommen, die Tabelle enthält 100.000.000 Zeilen.
Das Beste, was ich finden kann, ist ein Deckungsindex, der jede der "optionalen" Spalten enthält:
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Dies gibt mir einen Abfrageplan wie folgt:
- WÄHLEN
- Filter
- oben
- Sequenzprojekt (Skalar berechnen)
- Segment
- Index suchen
- Segment
- Sequenzprojekt (Skalar berechnen)
- oben
- Filter
Es scheint ziemlich gut zu sein. Etwa 80% -90% der Kosten stammen aus der idealen Indexsuchoperation.
Gibt es bessere Strategien für die Implementierung dieser Art der Suche?
Ich möchte die optionale Filterung nicht unbedingt auf den Client verlagern, da in einigen Fällen die Ergebnismenge aus dem "festen" Teil 100 oder 1000 sein kann. Der Client ist dann auch für das Sortieren und Paging verantwortlich, was für den Client möglicherweise zu viel Arbeit bedeutet.
quelle
RowNum BETWEEN 101 AND 200
?Antworten:
Wenn diese bestimmte Arbeitslast die Mehrheit der Abfragen für die Tabelle darstellt, können Sie Folgendes berücksichtigen:
Überlegungen:
Vorteile:
quelle
Ich habe diese Technik in der Vergangenheit verwendet. Die Tabelle war bei weitem nicht so groß, aber die Suchkriterien waren komplexer.
Dies ist die Kurzversion.
quelle
Angesichts Ihrer ersten beiden Voraussetzungen würde ich mir einen Clustered-Index ansehen
InsertDateTime
.quelle
Warum ziehen Sie keine Partitionierung in Betracht? Es ist ab SQL 2008 verfügbar, erfordert jedoch die Enterprise Edition (oder Developer Edition).
Grundsätzlich teilen Sie Ihre Tabelle auf mehrere Partitionen auf und definieren Ihre Partitionskriterien (Funktion). Wäre Ihr Datumsbereich?
https://www.simple-talk.com/sql/database-administration/gail-shaws-sql-server-howlers/
quelle
Wenn die Clients immer wieder auf fast dieselbe Weise filtern, können Sie einen Index für diese Abfragen erstellen.
Wenn der Client beispielsweise nach SiteId und StatusId filtert, können Sie einen zusätzlichen Index erstellen:
Auf diese Weise können die meisten "häufigeren" Abfragen schnell ausgeführt werden.
quelle