Ich entwerfe eine Tabelle mit einem sehr speziellen Verwendungsmuster. Die Tabelle wird fortlaufend mit begrenztem Datenverkehr protokolliert - ~ 25 Datensätze pro Sekunde, und dann führe ich jede Nacht eine einzige große Abfrage durch, um viele Daten zu extrahieren.Optimieren Sie meine Azure SQL PaaS-Tabelle und/oder Abfrage, um die Leistung zu erhöhen
Meine Tabellenerstellung Skript sieht derzeit wie folgt aus:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (select * from sysobjects where name='records' and xtype='U')
CREATE TABLE [dbo].[records](
[TripID] varchar(255) NOT NULL,
[RecordTimeUTC] datetime2(0) NOT NULL,
[TimeOfDaySeconds] [int] NOT NULL,
[T0Latitude] [float] NOT NULL,
[T0Longitude] [float] NOT NULL,
[T1Latitude] [float] NULL,
[T1Longitude] [float] NULL,
[T2Latitude] [float] NULL,
[T2Longitude] [float] NULL,
[T3Latitude] [float] NULL,
[T3Longitude] [float] NULL,
[T4Latitude] [float] NULL,
[T4Longitude] [float] NULL,
[T5Latitude] [float] NULL,
[T5Longitude] [float] NULL,
[VehicleID] [int] NULL,
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
) ON [PRIMARY]
GO
IF NOT EXISTS (select * from sys.indexes where name='TripIDRecordTimeIndex' and object_id = OBJECT_ID('dbo.records'))
CREATE INDEX TripIDRecordTimeIndex ON records (TripID, RecordTimeUTC desc)
GO
IF NOT EXISTS (select * from sys.indexes where name='TripIDIndex' and object_id = OBJECT_ID('dbo.records'))
CREATE INDEX TripIDIndex ON records (TripID)
GO
IF NOT EXISTS (select * from sys.indexes where name='RecordTimeUTCIndex' and object_id = OBJECT_ID('dbo.records'))
CREATE INDEX RecordTimeUTCIndex ON records (RecordTimeUTC desc)
GO
IF NOT EXISTS (select * from sys.objects where name like 'UniqueConstraint2' and parent_object_id = OBJECT_ID('dbo.records'))
ALTER TABLE [dbo].[records] ADD CONSTRAINT UniqueConstraint2 UNIQUE(VehicleID, RecordTimeUTC desc);
GO
IF NOT EXISTS (select * from sys.indexes where name='VehicleIDIndex' and object_id = OBJECT_ID('dbo.records'))
CREATE INDEX VehicleIDIndex ON records (VehicleID)
GO
Ich habe derzeit rund 60 Millionen Datensätze in meinem Tisch, und es ist unter 50 GB groß.
Die Abfrage zum Extrahieren von Daten ist sehr zeitaufwendig. Es dauert derzeit über eine Stunde. Ich bin mir nicht sicher, ob es mein Tabellenentwurf oder das Abfragedesign ist, das die Grundursache ist (obwohl beide wahrscheinlich).
Ich muss die letzte X Menge der Elemente für jede TripID in einer Reihe von TripIDs, die ich angeben, extrahieren. Es gibt ungefähr 10k verschiedene IDs und ich möchte in der Regel ungefähr die Hälfte von ihnen abfragen. X variiert zwischen ihnen auch, so mein besten Weg, um Abfrage ist derzeit ein Skript zu erzeugen, die ein bisschen wie folgt aussieht:
SELECT rs.* FROM (SELECT *, ROW_NUMBER() over (Partition BY TripID ORDER BY RecordTimeUTC DESC) AS Rank FROM records where TripID in (20141000,20441000,30011022,30011021,30011008,30012029,30012028,30012027,30011007,30011019,30011018,30012026,30012025,30012024,30011017,30011016,30012023,30012022,30011015,30011014,30012021,30012020,30011013,30011012,30013000,30013001,30013019,30013009,30011011,30011010,30011009,30013008,30013007,30012010,30012009,30013005,30013004,30013003,30012014,30012019,30013021,30013020,30011006,30011004,30012018,30012017,30012016,30013006,30011003,30011002,30012015,30012013,30013013,30013002,30011001,30011000,30011020,30012012,30012011,30011005,30011030,30012001,30012008,30012007,30011029,30011028,30012006,30012005,30011031,30011027,30012004,30012003,30011026,30011025,30011024,30012002,30012000,30012031,30011023,30012030,30015005,30016006,30016013,30016012,30014020,30014019,30014018,30016011,30016010,30014017,30014016,30016009,30016008,30014015,30014013,30014012,30016005,30016004,30016003,30014010,30014009,30016002,30016001,30014008,30014007,30016000,30016007,30014006,30014005,30014004,30014003,30014002,30014001,30014000,30014023,30014014,30015012,30015004,30015003,30013018,30013017,30015002,30015001,30013016,30013015,30013014,30015000,30015013,30015011,30013012,30013011,30015010,30015009,30013010,30014011,30015008,30015007,30014022,30014021,30015006,33651001,33661006)) rs WHERE Rank <= 690
UNION
SELECT rs.* FROM (SELECT *, ROW_NUMBER() over (Partition BY TripID ORDER BY RecordTimeUTC DESC) AS Rank FROM records where TripID in (20431003,20431002,20431001,20432003,20432002,20432001,30221001,33861002,33861003)) rs WHERE Rank <= 855
UNION
SELECT rs.* FROM (SELECT *, ROW_NUMBER() over (Partition BY TripID ORDER BY RecordTimeUTC DESC) AS Rank FROM records where TripID in (20171029,20171030,20002002,26122001)) rs WHERE Rank <= 45
UNION
...
(Die obige Abfrage gibt 690 Instanzen jede Reise in der ersten Liste, 855 Fälle von jeweils in der zweiten, 45 in der dritten usw. Die Abfrage ist viel größer als das - das ist nur ein Ausschnitt davon. Insgesamt extrahiere ich 10-15 Millionen Zeilen)
Wie bereits erwähnt meine Leistung ist schrecklich. Ist es eine Cloud-Sache? Ist es eine Designsache? Soll ich einen Clustered-Index verwenden? (Versuchte das für TripID, aber das war noch schlimmer). Kann ich meine Anfrage irgendwie verbessern? Extrahieren Sie für jede ID zum Beispiel die gleiche Anzahl von Instanzen und filtern Sie danach?
Ich merke, ich habe ein paar zusätzliche Indizes, die möglicherweise nicht in meiner Abfrage verwendet werden. Ich habe gerade versucht, mehr hinzuzufügen, da die Insert-Performance kein Problem darstellt. Der TripIDRecordTimeIndex sollte in meiner Abfrage verwendet werden.
Selbst wenn ich den Datentarif in Azure SQL auf S7 (800 DPU) hochskaliere, bekomme ich das nicht schnell. Jede Rückmeldung wird geschätzt.
Edit: Ich habe vor kurzem die TripID von int in varchar (255) geändert - würde dies meine Leistung brechen?
Download link to full execution plan
Edit3: Dachte, dass Anführungszeichen Hinzufügen ('') um die TripIDs, dass ich enorm zu verbessern die Leistung abfragen!
Edit4: Ich habe den Index von TheGameiswar hinzugefügt - und der Unterschied ist Tag und Nacht! Vielen Dank! Neuer Ausführungsplan beigefügt.
Dies ist eine sehr breite Frage. Haben Sie sich zunächst den SQL-Ausführungsplan für Ihre Abfragen angesehen? –
Dies ist ein Bereich, über den ich sehr wenig weiß. Ich habe eine Kopie des Ausführungsplans für eine Teilmenge des Ausführungsplans am Ende der Frage hinzugefügt. Ich weiß, dass es eine breite Frage ist, aber der Grund ist, dass ich nicht weiß, wo ich hinschauen soll. Danke für Ihre Rückmeldung. – WPFUser
Ein Bild eines Plans ist kein Abfrageplan. Sie müssen auf die Datei verlinken: https://meta.stackexchange.com/questions/47689/how-can-i-attach-a-file-to-a-stack-overflow-post –