กลยุทธ์การสืบค้นโดยใช้ตารางเวลาชั่วคราวของระบบ SQL Server 2016 สำหรับมิติที่เปลี่ยนแปลงช้า


17

เมื่อใช้ตารางชั่วคราวของระบบ (ใหม่ใน SQL Server 2016) การเขียนแบบสอบถามและความหมายของประสิทธิภาพเมื่อใช้คุณลักษณะนี้เพื่อจัดการมิติการเปลี่ยนแปลงอย่างช้า ๆ ในคลังข้อมูลเชิงสัมพันธ์ขนาดใหญ่

ตัวอย่างเช่นสมมติว่าฉันมีCustomerมิติ100,000 แถวพร้อม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 ล้านแถวด้วย


ทำไมจึงจำเป็นต้องนับจำนวนการเปลี่ยนแปลงต่อลูกค้า ลูกค้าที่เปลี่ยนรหัสไปรษณีย์ในระหว่างปีจะเพิ่มความซับซ้อนให้กับแบบสอบถาม แต่จริงๆแล้วการรายงานเกี่ยวกับการเปลี่ยนแปลงเหล่านั้นไม่จำเป็นต้องมี
Justin Grant

@JustinGrant จำนวนการเปลี่ยนแปลงคือแสดงให้เห็นว่าการกลายพันธุ์เหล่านี้สามารถดึงข้อมูลจากข้อมูลประวัติได้อย่างไร อย่างไรก็ตามคุณได้เพิ่มเมื่อวานนี้: ข้อความค้นหา "การขายด้วยรหัสไปรษณีย์" ของฉันควรจะสามารถคำนวณผลลัพธ์ที่ถูกต้องได้โดยไม่คำนึงถึงการเปลี่ยนแปลงของรหัสไปรษณีย์ของลูกค้าเมื่อเวลาผ่านไป ทำให้คำขอชัดเจนยิ่งขึ้น ในกรณีนั้น SYSTEM_TIME ควรตั้งค่าแบบเดียวกันสำหรับทั้งสองตาราง และมีสองวิธี: 1) ใช้ตารางที่ถูกลิดรอนและใช้ system_time สำหรับทั้งสองตาราง 2) หรือเพียงแค่สร้างมุมมองที่ถือการเข้าร่วมและใช้ SYSTEM_TIME ในการสอบถามมุมมอง
Alexandr Volok
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.