Abfragestrategien unter Verwendung von SQL Server 2016-Systemversion-Temporaltabellen für sich langsam ändernde Dimensionen


17

Welche Auswirkungen haben die Erstellung von Abfragen und die Leistung bei der Verwendung einer vom System versionierten temporalen Tabelle (neu in SQL Server 2016), wenn diese Funktion zum langsamen Ändern von Dimensionen in einem großen relationalen Data Warehouse verwendet wird?

Angenommen, ich habe eine CustomerDimension von 100.000 Zeilen mit einer Postal CodeSpalte und eine SalesFaktentabelle mit mehreren Milliarden Zeilen mit einer CustomerIDFremdschlüsselspalte. Angenommen, ich möchte "Gesamtumsatz 2014 nach Postleitzahl des Kunden" abfragen. Die vereinfachte DDL sieht folgendermaßen aus (der Übersichtlichkeit halber werden viele Spalten weggelassen):

CREATE TABLE Customer
(
    CustomerID int identity (1,1) NOT NULL PRIMARY KEY CLUSTERED, 
    PostalCode varchar(50) NOT NULL,
    SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL, 
    SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL,   
    PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime) 
)
WITH (SYSTEM_VERSIONING = ON);

CREATE TABLE Sale
(
    SaleId int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    SaleDateTime datetime2 NOT NULL,
    CustomerId int NOT NULL FOREIGN KEY REFERENCES Customer(CustomerID),
    SaleAmount decimal(10,2) NOT NULL
);

Interessant wird, dass Kunden möglicherweise im Laufe des Jahres umgezogen sind, sodass derselbe Kunde möglicherweise unterschiedliche Postleitzahlen hat. Und es ist sogar aus der Ferne möglich, dass ein Kunde weggezogen ist und dann zurückgezogen ist, was bedeutet, dass es mehrere Verlaufsdatensätze für denselben Kunden mit derselben Postleitzahl geben kann! Meine Abfrage "Umsatz nach Postleitzahl" sollte in der Lage sein, korrekte Ergebnisse zu berechnen, unabhängig davon, wie sich die Postleitzahlen der Kunden im Laufe der Zeit ändern.

Ich verstehe, wie Temporaltabellen verwendet werden, um nur die Kundendimension abzufragen (z. B. SELECT * FROM Customer FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'), bin mir jedoch nicht sicher, wie ich die Faktentabelle am genauesten und effizientesten verknüpfen kann.

Soll ich das so abfragen?

SELECT c.PostalCode, sum(s.SaleAmount) SaleAmount
FROM Customer c FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'
    JOIN Sale s ON s.CustomerId = c.CustomerId
WHERE s.SaleDateTime >= '2014-1-1' AND s.SaleDateTime < '2015-1-1'
    AND c.SysStartTime >= s.SaleDateTime
    AND c.SysEndTime < s.SaleDateTime
GROUP BY c.PostalCode

Und auf welche Leistungsaspekte sollte ich bei solchen Abfragen achten?

Antworten:


1

Ich denke, in Ihrem Fall ist eine abgeleitete Tabelle erforderlich, um die Anzahl der mutierten Postleitzahlen pro Kunde zu ermitteln:

SELECT c.postalcode 
, sum(s.SaleAmount) SaleAmount
, count(postcode_mutations.customerid) as CntCustomerChangedPostCode   
FROM dbo.Sale s
JOIN dbo.Customer c on s.customerid = c.customerid

LEFT JOIN (
SELECT 
    CustomerID
FROM [dbo].[Customer]
FOR SYSTEM_TIME FROM '20140101' TO '20150101'
GROUP BY CustomerID
HAVING COUNT(DISTINCT PostalCode) > 1
) postcode_mutations on s.customerid = postcode_mutations.customerid

WHERE s.SaleDateTime >= '2014-1-1' AND s.SaleDateTime < '2015-1-1'
GROUP BY c.PostalCode

upd: Da die Abfrage DWH / Analytics-Szenarien bedienen soll, kann die Indizierung des Spaltenspeichers überprüft werden. Zuvor habe ich auch einige Benchmarks für eine 10-Millionen-Zeilen-Tabelle erstellt.


Warum muss die Anzahl der Änderungen pro Kunde gezählt werden? Kunden, die ihre Postleitzahl im Laufe des Jahres ändern, erhöhen zwar die Komplexität der Abfrage, es scheint jedoch nicht erforderlich zu sein, über diese Änderungen zu berichten.
Justin Grant

@JustinGrant Die Anzahl der Änderungen soll zeigen, wie diese Mutationen aus den historischen Daten abgerufen werden können. Diese Zeilen haben Sie jedoch gestern hinzugefügt: Meine Abfrage "Umsatz nach Postleitzahl" sollte in der Lage sein, korrekte Ergebnisse zu berechnen, unabhängig davon, wie sich die Postleitzahlen der Kunden im Laufe der Zeit ändern. Machen Sie die Anfrage klarer. In diesem Fall sollte SYSTEM_TIME für beide Tabellen auf dieselbe Weise festgelegt werden. und es gibt zwei Möglichkeiten: 1) Verwenden Sie beraubte Tabellen und wenden Sie system_time für beide Tabellen an. 2) Oder erstellen Sie einfach eine Ansicht, die einen Join enthält, und wenden Sie SYSTEM_TIME beim Abfragen der Ansicht an
Alexandr Volok
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.