Стратегії запитів із використанням тимчасових таблиць, розроблених системою SQL Server 2016, для повільно змінюваних розмірів


17

Використовуючи тимчасову таблицю з версією системи (нову в SQL Server 2016), які наслідки щодо створення запитів та продуктивності, коли ця функція використовується для обробки повільних змін розмірів у великому сховищі реляційних даних?

Наприклад, припустимо, що у мене Customerрозмір 100000 рядків зі Postal Codeстовпцем та багатомільярдна Salesтаблиця фактів із CustomerIDстовпцем із зовнішнім ключем. І припустимо, я хочу запитувати "Загальний обсяг продажів за 2014 рік за поштовим індексом клієнта". Спрощений DDL виглядає так (опускаючи безліч стовпців для наочності):

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
);

Цікаво, що клієнти могли переїхати протягом року, тому той самий клієнт може мати різні поштові індекси. І навіть віддалено можливо, що клієнт відсунувся, а потім переїхав назад, це означає, що для одного і того ж клієнта може бути кілька записів історії з тим самим поштовим індексом! Мій запит "продаж за поштовим індексом" повинен мати можливість обчислити правильні результати, незалежно від того, як змінюються поштові індекси клієнтів у часі.

Я розумію, як використовувати тимчасові таблиці для запиту лише на розмір клієнта (наприклад SELECT * FROM Customer FOR SYSTEM_TIME FROM '2014-1-1' TO '2015-1-1'), але я не впевнений, як найбільш точно та ефективно приєднатися до таблиці фактів.

Це я повинен запитати?

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

І які міркування щодо ефективності, на які я повинен слідкувати, коли роблю такі запити?

Відповіді:


1

Я думаю, у вашому випадку необхідна отримана таблиця, щоб виділити запит на кількість мутацій поштових індексів на кожного клієнта:

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: Оскільки запит повинен обслуговувати сценарії DWH / Analytics, індексування магазину стовпців - це можливість перевірити. Я також зробив кілька орієнтирів раніше для таблиці 10 мільйонів рядків.


Чому потрібно рахувати кількість змін на кожного клієнта? Клієнти, які змінюють поштовий індекс протягом року, додають складності запиту, але фактично звітувати про ці зміни, здається, не потрібно.
Джастін Грант

@JustinGrant Кількість змін полягає в тому, щоб показати, як ці мутації можна отримати з історичних даних. Однак ці рядки, які ви додали вчора: Мій запит про "продаж за поштовим індексом" повинен мати можливість обчислити правильні результати, незалежно від того, як змінюються поштові індекси клієнтів у часі. Зробити запит більш чітким. У цьому випадку SYSTEM_TIME слід встановити однаково для обох таблиць. і є два способи: 1) Використовуйте позбавлені таблиці та застосуйте system_time до обох таблиць. 2) Або просто створіть подання, яке містить приєднання, і застосуйте SYSTEM_TIME для запиту на перегляд
Олександр Волок
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.