Wir verwenden eine Vendor App, die unter SQL Server Enterprise ausgeführt wird, und es ist ziemlich ärgerlich, COUNT
Anweisungen in der Items-Tabelle auszuführen, während die meisten Finanzdokumente (Bestellungen, Rechnungen usw.) verarbeitet werden.
Z.B SELECT COUNT('A') FROM [dbo].[Items] T0
Ich bin mir sicher, dass das normalerweise in Ordnung wäre, aber es gibt über 6 Millionen Datensätze, und es dauert ungefähr 400 ms, um sie alle zu zählen. Dies kann einen wesentlichen Teil der gesamten Verarbeitungszeit ausmachen.
Die Tabelle enthält bereits einen extrem engen NonClustered-Index (tinyint plus Clustered Key), den SQL beim Tabellenscan verwendet. Ich denke, wir können diesbezüglich keine besseren Ergebnisse erzielen.
Mir sind einige Lösungen bekannt, die wir nach Möglichkeit vermeiden möchten:
- Indizierte Ansicht mit
COUNT_BIG(*)
- Verwenden Sie schnellere Prozessoren - wir verwenden Cloud-Server, und diesbezüglich gibt es nur sehr begrenzte Optionen.
- Datensätze löschen - in diesem Fall keine Option.
Haben wir andere Möglichkeiten, dies zu beschleunigen?
Hier ist eine Übersicht über das Setup: https://gist.github.com/elvishfiend/5094f120b14f8ecfb325623edcb5f3eb
quelle
Antworten:
Die indizierte Ansicht sollte bei optimaler Implementierung zu den schnellsten Optionen mit dem geringsten Wartungsaufwand gehören .
Änderungen sind inkrementell (Deltas), wie ich in der Wartung der indizierten Ansicht in Ausführungsplänen ausführlich erläutere (eine vollständige Nachzählung wird nicht bei jeder Aktualisierung der Basistabelle durchgeführt). Sie müssen jedoch sicherstellen, dass die Delta-Aktualisierungsteile des Ausführungsplans über effiziente Zugriffsmethoden verfügen (wie jede Abfrage).
Es ist normalerweise recht einfach, einen fehlenden Index aus dem
INSERT/UPDATE/DELETE
Ausführungsplan zu identifizieren . Vielleicht könnten Sie Ihrer Frage einen veranschaulichenden (tatsächlichen) Ausführungsplan nach der Ausführung hinzufügen.Der automatische Abgleich von Abfragetext mit einer indizierten Ansicht ist nur in Enterprise Edition (und entsprechenden Entsprechungen) verfügbar. In anderen Editionen müssen Sie den
WITH (NOEXPAND)
Tabellenhinweis verwenden. Es gibt auch gute Gründe ,NOEXPAND
auch auf Enterprise Edition zu verwenden.Zum Demo-Code: Stellen Sie sicher, dass Sie den Hinweis mit angeben
WITH (NOEXPAND)
. Die Art und Weise, wie Sie es geschrieben haben,NOEXPAND
wird als Alias analysiert. Beachten Sie auch, dass nur materialisierte (indizierte) Ansichten einenNOEXPAND
Hinweis haben können.Wenn Sie keinen Hinweis direkt hinzufügen können, ist dies eine hervorragende Verwendung eines Planleitfadens. Ein Planleitfaden kann auch verwendet werden, um sicherzustellen, dass eine Abfrage, die einer indizierten Ansicht entspricht (ohne sie explizit zu benennen), tatsächlich die indizierte Ansicht verwendet.
Denken Sie daran, dass
NOEXPAND
SQL Server ohne eine materialisierte (indizierte) Ansicht die Ansichtsdefinition immer zu Beginn der Planerstellung erweitert. Die Enterprise Edition kann (Teile) einer Abfrage mit einer indizierten Ansicht abgleichen (oder auch nicht), abhängig von der Bewertung der Kosten für jede Option.Verwandte Fragen und Antworten:
quelle
Wenn Sie mit SQL Server 2012 nicht weiterkommen, können Sie versuchen, einen Index nur für den Clustered-Indexschlüssel zu erstellen. Es ist möglicherweise etwas kleiner als ein Index für eine
TINYINT
Spalte. Sie können auch versuchen, Ihrem Index eine Seitenkomprimierung hinzuzufügen. Das könnte Ihre Abfrage beschleunigen, hängt jedoch von den Daten in der Tabelle ab.Wenn Sie ein Upgrade auf SQL Server 2016 durchführen können, können Sie einen nicht gruppierten Columnstore-Index für die Tabelle erstellen. Dadurch werden
COUNT(*)
Abfragen extrem schnell und der Aufwand für DML-Vorgänge ist geringer. Hier ist eine kurze Demo:Mit der NCCI kann ich sechs Millionen Zeilen in weniger als 20 ms zählen.
quelle
Sie können eine ID-Spalte hinzufügen, die Sie manuell aktualisieren, sodass es immer in der Reihenfolge Regen, Sommer oder Winter kommt.
Wenn Sie eine einzelne Tabelle haben und es keine Where-Bedingung oder Join gibt, dann
Ich höre, dass es nicht von aktualisierten Statistiken abhängt. Ich bin nicht sicher.
sp_spaceused employee
Dies hängt von aktualisierten Statistiken ab.Sie können so etwas wie einen Job erstellen, der einmal ausgeführt wird und die neueste ID und Anzahl speichert
Erstellen Sie die Tabelle ItemCount als Latestid int nicht null, LatestCount int nicht null
Die Itemcount-Tabelle enthält immer nur 1 Zeilen und benötigt keinen Index
- Hier ist die Zähllogik Ihre eigene
Wenn Ihre Anfrage eine Zählung erfordert, können Sie dies tun:
Hier
[dbo].[Items]
sollte die Itemid-Spalte indiziert werdenDies ist auch geeignet, wenn
join and filter
Ihrecount (*)
Anfrage eine Bedingung enthältquelle