W przypadku korzystania z tabeli czasowej z wersją systemową (nowość w SQL Server 2016), jakie są skutki tworzenia zapytań i wydajności, gdy ta funkcja jest używana do obsługi powolnej zmiany wymiarów w dużej relacyjnej hurtowni danych?
Załóżmy na przykład, że mam Customer
wymiar 100 000 wierszy z Postal Code
kolumną i Sales
tabelę faktów zawierającą wiele miliardów wierszy z CustomerID
kolumną klucza obcego. I załóżmy, że chcę zapytać „Sprzedaż ogółem 2014 według kodu pocztowego klienta”. Uproszczony DDL wygląda tak (z pominięciem wielu kolumn dla przejrzystości):
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
);
Ciekawe jest to, że klienci mogli się przeprowadzić w ciągu roku, więc ten sam klient może mieć różne kody pocztowe. Jest nawet możliwe, że klient przeprowadził się, a następnie wycofał, co oznacza, że może istnieć wiele rekordów historii dla tego samego klienta z tym samym kodem pocztowym! Moje zapytanie dotyczące „sprzedaży według kodu pocztowego” powinno być w stanie obliczyć prawidłowe wyniki bez względu na to, jak zmieniają się z czasem kody pocztowe klientów.
Rozumiem, jak korzystać z tabel czasowych do zapytania samego wymiaru klienta (np. SELECT * FROM Customer FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'
), Ale nie jestem pewien, jak najdokładniej i najskuteczniej dołączyć do tabeli faktów.
Czy w ten sposób powinienem zapytać?
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
A jakie są uwagi dotyczące wydajności, na które powinienem uważać, gdy zadajemy takie zapytania?