2

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?

Edit2: Ausführungsplan: Execution plan snip

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.

New Execution plan

+0

Dies ist eine sehr breite Frage. Haben Sie sich zunächst den SQL-Ausführungsplan für Ihre Abfragen angesehen? –

+0

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

+0

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 –

Antwort

2
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.....)) rs WHERE Rank <= 690 

Die Indizes Sie haben für unter Teil Abfrage nicht usefull ...

SELECT *, 
ROW_NUMBER() over (Partition BY TripID ORDER BY RecordTimeUTC DESC) 
AS Rank FROM records where TripID in 

Ich würde einen Index wie erstellen unter

create index nci_sometst on table (tripid,recorddatetime) 
include(<remaining columsn you are selecting>) 

Die obige Abfrage in immer Aufzeichnungen für teilweise von tripID helfen können, aber dann abgeleitete Tabelle, die Sie Berechnung Rang verwenden, kann dies nicht der sein, viel Hilfe, wenn Ihr Ergebnis von inneren Abfrage ist groß ..

Ich würde wahrscheinlich dies in eine temporäre Tabelle und erstellen Sie einen Index auf Rang, so dass dies auch hilfreich für andere Union Abfragen ist.

hatte auch einen Blick auf Ihrem Ausführungsplan, und ich kann Sie scannen die gleiche Tabelle mehrere Male sehen und viele Zeilen jedes Mal

enter image description here

Auch ohne Datentypumwandlung Warnungen zu lesen, Ihre Abfrage wird nicht Verwenden Sie einen der Indizes, die Sie effektiv haben

+1

Das hat den Trick wirklich geschafft! Es hat eine Weile gedauert, um zu erstellen, aber sobald alle Anfragen sind fast sofort! Vielen Dank! PS: Ich frage nur einmal nach jeder TripID, also glaube ich nicht, dass die temporäre Tabelle geholfen hätte. – WPFUser

+1

Froh, dass es Ihnen geholfen hat, wenn Sie mehr Details zur Verfügung stellen können, die auch in Zukunft hilfreich sein könnten. "Fragen, die nach Performance-Hilfe suchen, sollten DDL, DML der beteiligten Tabellen zusammen mit Testdaten enthalten. Wenn Ihre Testdaten groß sind, versuchen Sie es scripting out Schema und Statistiken für die Tabelle (rechte Maustaste Datenbank-> Skripte generieren-> bestimmte Datenbankobjekte auswählen-> im nächsten Bildschirm wählen Sie erweiterte und wählen Sie Skript Statistiken) und fügen Sie es in Frage..Mit dieser Info repro das gleiche Problem Sie werden konfrontiert.Andernfalls wird es sehr schwierig, Ihre Frage zu beantworten. Die Server-Version hilft auch " – TheGameiswar

Verwandte Themen