느리게 변경되는 차원에 대해 SQL Server 2016 시스템 버전 임시 테이블을 사용하는 쿼리 전략


17

시스템 버전 임시 테이블을 사용할 때 (SQL Server 2016의 새로운 기능)이 기능을 사용하여 대규모 관계형 데이터웨어 하우스에서 느리게 변경되는 차원을 처리 할 때 쿼리 제작 및 성능에 어떤 영향을 미칩니 까?

예를 들어 열이 10 만 행 이고 외래 키 열이 수십억 행인 팩트 테이블이 있다고 가정 Customer합니다 . 그리고 "고객의 우편 번호 별 총 2014 년 판매량"을 쿼리하려고한다고 가정하십시오. 단순화 된 DDL은 다음과 같습니다 (명확성을 위해 많은 열을 생략 함).Postal CodeSalesCustomerID

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

흥미로운 점은 고객이 1 년 동안 이사했을 수 있으므로 동일한 고객이 다른 우편 번호를 가질 수 있다는 것입니다. 또한 고객이 멀리 이동했다가 다시 이동할 수도 있습니다. 즉, 동일한 우편 번호로 동일한 고객에 대해 여러 이력 기록이있을 수 있습니다. "우편 번호 별 판매"에 대한 나의 쿼리는 고객의 우편 번호가 시간이 지남에 따라 어떻게 변하는 지에 관계없이 정확한 결과를 계산할 수 있어야합니다.

임시 테이블을 사용하여 고객 차원 만 쿼리하는 방법을 이해 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 시나리오를 제공해야하므로 columnstore 인덱싱은 확인하는 옵션입니다. 또한 이전 에 천만 행 테이블 대한 벤치 마크를 만들었습니다 .


고객 당 변경 횟수를 계산해야하는 이유는 무엇입니까? 연중 우편 번호를 변경하는 고객은 쿼리에 복잡성을 추가하지만 실제로 이러한 변경 사항을보고 할 필요는 없습니다.
저스틴 그랜트

@JustinGrant 변경 횟수는 이러한 돌연변이가 기록 데이터에서 검색되는 방법을 보여주는 것입니다. 그러나 이러한 행은 어제 추가했습니다. "우편 번호 별 판매"에 대한 내 쿼리는 시간이 지남에 따라 고객의 우편 번호가 어떻게 변하는 지에 관계없이 올바른 결과를 계산할 수 있어야합니다. 더 명확하게 요청하십시오. 이 경우 SYSTEM_TIME은 두 테이블에 대해 동일한 방식으로 설정되어야합니다. 두 가지 방법이 있습니다. 1) 권한이없는 테이블을 사용하고 두 테이블 모두에 system_time을 적용하십시오. 2) 또는 단순히 조인을 유지하고 뷰를 쿼리 할 때 SYSTEM_TIME을 적용하는 뷰를 생성하십시오
Alexandr Volok
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.