Ich habe ein E / A-Problem mit einem großen Tisch.
Allgemeine Statistiken
Die Tabelle weist die folgenden Hauptmerkmale auf:
- Umgebung: Azure SQL-Datenbank (Stufe ist P4 Premium (500 DTUs))
- Zeilen: 2.135.044.521
- 1.275 gebrauchte Partitionen
- Clustered und partitionierter Index
Modell
Dies ist die Tabellenimplementierung:
CREATE TABLE [data].[DemoUnitData](
[UnitID] [bigint] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[Value1] [decimal](18, 2) NULL,
[Value2] [decimal](18, 2) NULL,
[Value3] [decimal](18, 2) NULL,
CONSTRAINT [PK_DemoUnitData] PRIMARY KEY CLUSTERED
(
[UnitID] ASC,
[Timestamp] ASC
)
)
GO
ALTER TABLE [data].[DemoUnitData] WITH NOCHECK ADD CONSTRAINT [FK_DemoUnitData_Unit] FOREIGN KEY([UnitID])
REFERENCES [model].[Unit] ([ID])
GO
ALTER TABLE [data].[DemoUnitData] CHECK CONSTRAINT [FK_DemoUnitData_Unit]
GO
Die Partitionierung hängt damit zusammen:
CREATE PARTITION SCHEME [DailyPartitionSchema] AS PARTITION [DailyPartitionFunction] ALL TO ([PRIMARY])
CREATE PARTITION FUNCTION [DailyPartitionFunction] (datetime) AS RANGE RIGHT
FOR VALUES (N'2017-07-25T00:00:00.000', N'2017-07-26T00:00:00.000', N'2017-07-27T00:00:00.000', ... )
Servicequalität
Ich denke, die Indizes und Statistiken werden jede Nacht durch schrittweise Neuerstellung / Reorganisation / Aktualisierung gut gepflegt.
Dies sind die aktuellen Indexstatistiken der am häufigsten verwendeten Indexpartitionen:
Dies sind die aktuellen Statistik-Eigenschaften der am häufigsten verwendeten Partitionen:
Problem
Ich führe eine einfache Abfrage mit hoher Frequenz für die Tabelle aus.
SELECT [UnitID]
,[Timestamp]
,[Value1]
,[Value2]
,[Value3]
FROM [data].[DemoUnitData]
WHERE [UnitID] = 8877 AND [Timestamp] >= '2018-03-01' AND [Timestamp] < '2018-03-13'
OPTION (MAXDOP 1)
Der Ausführungsplan sieht folgendermaßen aus: https://www.brentozar.com/pastetheplan/?id=rJvI_4TtG
Mein Problem ist, dass diese Abfragen eine extrem hohe Anzahl von E / A-Operationen erzeugen, was zu einem Engpass bei PAGEIOLATCH_SH
Wartezeiten führt.
Frage
Ich habe gelesen, dass PAGEIOLATCH_SH
Wartezeiten oft mit nicht gut optimierten Indizes zusammenhängen. Gibt es Empfehlungen für mich, wie ich E / A-Vorgänge reduzieren kann? Vielleicht durch Hinzufügen eines besseren Index?
Antwort 1 - bezogen auf Kommentar von @ S4V1N
Der veröffentlichte Abfrageplan stammt aus einer Abfrage, die ich in SSMS ausgeführt habe. Nach Ihrem Kommentar recherchiere ich zum Serververlauf. Die vom Dienst ausgeführte Abfrage sieht etwas anders aus (EntityFramework-bezogen).
(@p__linq__0 bigint,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7))
SELECT 1 AS [C1], [Extent1]
.[Timestamp] AS [Timestamp], [Extent1]
.[Value1] AS [Value1], [Extent1]
.[Value2] AS [Value2], [Extent1]
.[Value3] AS [Value3]
FROM [data].[DemoUnitData] AS [Extent1]
WHERE ([Extent1].[UnitID] = @p__linq__0)
AND ([Extent1].[Timestamp] >= @p__linq__1)
AND ([Extent1].[Timestamp] < @p__linq__2) OPTION (MAXDOP 1)
Auch der Plan sieht anders aus:
https://www.brentozar.com/pastetheplan/?id=H1fhALpKG
oder
https://www.brentozar.com/pastetheplan/?id=S1DFQvpKz
Und wie Sie hier sehen können, wird unsere DB-Leistung von dieser Abfrage kaum beeinflusst.
Antwort 2 - bezogen auf die Antwort von @Joe Obbish
Zum Testen der Lösung habe ich Entity Framework durch einen einfachen SqlCommand ersetzt. Das Ergebnis war eine erstaunliche Leistungssteigerung!
Der Abfrageplan ist jetzt der gleiche wie in SSMS, und die logischen Lese- und Schreibvorgänge fallen auf ~ 8 pro Ausführung.
Die gesamte E / A-Last sinkt auf fast 0!
Es erklärt auch, warum ich einen großen Leistungsabfall bekomme, nachdem ich den Partitionsbereich von monatlich auf täglich geändert habe. Das Fehlen der Partitionseliminierung führte dazu, dass mehr Partitionen gescannt werden mussten.