การเปรียบเทียบประสิทธิภาพระหว่างการใช้ฟังก์ชั่นเข้าร่วมและหน้าต่างเพื่อรับค่านำและระยะเวลาล่าช้า


11

ผมมีตารางที่มีแถว 20M และแต่ละแถวมี 3 คอลัมน์: time, และid valueสำหรับแต่ละidและtimeมีvalueสถานะ ฉันต้องการทราบว่านำและล่าช้าค่าของบางอย่างสำหรับการที่เฉพาะเจาะจงtimeid

ฉันใช้สองวิธีเพื่อให้ได้สิ่งนี้ วิธีการหนึ่งคือการใช้เข้าร่วมและอีกวิธีหนึ่งคือการใช้ฟังก์ชั่นหน้าต่างนำ / ล่าช้ากับดัชนีคลัสเตอร์บนและtimeid

ฉันเปรียบเทียบประสิทธิภาพของสองวิธีนี้ตามเวลาดำเนินการ วิธีการเข้าร่วมใช้เวลา 16.3 วินาทีและวิธีฟังก์ชั่นหน้าต่างใช้เวลา 20 วินาทีโดยไม่รวมเวลาในการสร้างดัชนี สิ่งนี้ทำให้ฉันประหลาดใจเพราะฟังก์ชั่นหน้าต่างดูเหมือนจะก้าวหน้าในขณะที่วิธีการเข้าร่วมนั้นดุร้าย

นี่คือรหัสสำหรับสองวิธี:

สร้างดัชนี

create clustered index id_time
 on tab1 (id,time)

เข้าร่วมวิธีการ

select a1.id,a1.time
   a1.value as value, 
   b1.value as value_lag,
   c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time

สถิติ IO ที่สร้างโดยใช้SET STATISTICS TIME, IO ON:

สถิติสำหรับวิธีการเข้าร่วม

นี่คือแผนการดำเนินการสำหรับวิธีการเข้าร่วม

วิธีการฟังก์ชั่นหน้าต่าง

select id, time, value, 
   lag(value,1) over(partition by id order by id,time) as value_lag,
   lead(value,1) over(partition by id order by id,time) as value_lead
into tab2
from tab1

(การสั่งซื้อโดยtimeประหยัดเพียง0.5 วินาที)

นี่คือแผนการดำเนินการสำหรับวิธีการทำงานของหน้าต่าง

สถิติ IO

[สถิติสำหรับฟังก์ชั่นหน้าต่างวิธีที่ 4]


ฉันจะตรวจสอบข้อมูลในsample_orig_month_1999และดูเหมือนว่าข้อมูลดิบได้รับคำสั่งอย่างดีจากและid timeนี่เป็นสาเหตุของความแตกต่างด้านประสิทธิภาพหรือไม่

ดูเหมือนว่าวิธีการรวมมีการอ่านแบบลอจิคัลมากกว่าวิธีฟังก์ชั่นหน้าต่างในขณะที่เวลาดำเนินการสำหรับอดีตนั้นน้อยกว่าจริง เป็นเพราะอดีตมีความเท่าเทียมที่ดีกว่า

ฉันชอบวิธีฟังก์ชั่นหน้าต่างเนื่องจากรหัสย่อมีวิธีใดที่จะเร่งความเร็วสำหรับปัญหาเฉพาะนี้หรือไม่

ฉันใช้ SQL Server 2016 บน Windows 10 64 บิต

คำตอบ:


11

ประสิทธิภาพของโหมดแถวLEADและLAGฟังก์ชันหน้าต่างที่ค่อนข้างต่ำเมื่อเทียบกับการรวมตัวเองนั้นไม่มีอะไรใหม่ ตัวอย่างเช่น Michael Zilberstein เขียนเกี่ยวกับเรื่องนี้ใน SQLblog.com ย้อนกลับไปในปี 2012 มีค่าใช้จ่ายค่อนข้างน้อยในส่วน (ซ้ำ), โครงการลำดับ, Window Spool และกระแสรวมผู้ประกอบการแผน:

ส่วนแผน

ใน SQL Server 2016 คุณมีตัวเลือกใหม่ซึ่งเป็นการเปิดใช้งานการประมวลผลโหมดแบตช์สำหรับการรวมหน้าต่าง สิ่งนี้ต้องการดัชนีเรียงคอลัมน์แบบเรียงบนตารางแม้ว่าจะว่างเปล่า ปัจจุบันการมีดัชนี columnstore เป็นสิ่งจำเป็นสำหรับเครื่องมือเพิ่มประสิทธิภาพในการพิจารณาแผนโหมดแบทช์ โดยเฉพาะอย่างยิ่งจะช่วยให้ผู้ปฏิบัติงานโหมดรวมแบทช์ที่มีประสิทธิภาพมากขึ้น

ในการทดสอบในกรณีของคุณให้สร้างดัชนี columnstore ที่ไม่มีการทำคลัสเตอร์ที่ว่างเปล่า:

 -- Empty CS index
CREATE NONCLUSTERED COLUMNSTORE INDEX dummy 
ON dbo.tab1 (id, [time], [value]) 
WHERE id < 0 AND id > 0;

แบบสอบถาม:

SELECT
    T1.id,
    T1.[time],
    T1.[value],
    value_lag = 
        LAG(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time]),
    value_lead =
        LEAD(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time])
FROM dbo.tab1 AS T1;

ตอนนี้ควรให้แผนการดำเนินการเช่น:

แผนร้านค้าแถวโหมดแบทช์

... ซึ่งอาจทำงานได้เร็วขึ้นมาก

คุณอาจต้องใช้OPTION (MAXDOP 1)คำใบ้หรือคำแนะนำอื่น ๆ เพื่อให้ได้รูปร่างตามแผนเหมือนกันเมื่อเก็บผลลัพธ์ไว้ในตารางใหม่ แผนรุ่นคู่ขนานต้องใช้การเรียงลำดับโหมดแบตช์ (หรืออาจเป็นสอง) ซึ่งอาจช้ากว่าเล็กน้อย มันค่อนข้างขึ้นอยู่กับฮาร์ดแวร์ของคุณ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวดำเนินการรวมหน้าต่างโหมดแบทช์ดูบทความต่อไปนี้โดย Itzik Ben-Gan:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.