เหตุใดตารางอุณหภูมิจึงเป็นโซลูชันที่มีประสิทธิภาพมากขึ้นสำหรับปัญหาฮาโลวีนมากกว่าตัวหลอดที่กระตือรือร้น


14

พิจารณาแบบสอบถามต่อไปนี้ที่แทรกแถวจากตารางต้นฉบับเฉพาะเมื่อยังไม่ได้อยู่ในตารางเป้าหมาย:

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);

รูปร่างแผนหนึ่งที่เป็นไปได้รวมถึงการรวมการผสานและสปูลที่กระตือรือร้น ผู้ประกอบการสปูลกระตือรือร้นที่จะนำเสนอเพื่อแก้ปัญหาฮาโลวีน :

แผนแรก

บนเครื่องของฉันรหัสด้านบนจะทำงานในเวลาประมาณ 6900 มิลลิวินาที รหัส Repro เพื่อสร้างตารางรวมอยู่ที่ด้านล่างของคำถาม หากฉันไม่พอใจกับการแสดงฉันอาจลองโหลดแถวเพื่อแทรกลงในตารางชั่วคราวแทนการใช้สปูลกระตือรือร้น การดำเนินการหนึ่งที่เป็นไปได้มีดังนี้:

DROP TABLE IF EXISTS #CONSULTANT_RECOMMENDED_TEMP_TABLE;
CREATE TABLE #CONSULTANT_RECOMMENDED_TEMP_TABLE (
    ID BIGINT,
    PRIMARY KEY (ID)
);

INSERT INTO #CONSULTANT_RECOMMENDED_TEMP_TABLE WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1);

รหัสใหม่รันในประมาณ 4400 มิลลิวินาที ฉันสามารถรับแผนจริงและใช้สถิติเวลาจริงเพื่อตรวจสอบเวลาที่ใช้ในระดับผู้ปฏิบัติงาน โปรดทราบว่าการขอแผนจริงเพิ่มค่าใช้จ่ายที่สำคัญสำหรับคิวรีเหล่านี้ดังนั้นผลรวมจะไม่ตรงกับผลลัพธ์ก่อนหน้า

╔═════════════╦═════════════╦══════════════╗
  operator    first query  second query 
╠═════════════╬═════════════╬══════════════╣
 big scan     1771         1744         
 little scan  163          166          
 sort         531          530          
 merge join   709          669          
 spool        3202         N/A          
 temp insert  N/A          422          
 temp scan    N/A          187          
 insert       3122         1545         
╚═════════════╩═════════════╩══════════════╝

แผนคิวรีที่มีสปูลกระตือรือร้นดูเหมือนจะใช้เวลากับตัวดำเนินการแทรกและสปูลอย่างมีนัยสำคัญเมื่อเปรียบเทียบกับแผนที่ใช้ตารางชั่วคราว

เหตุใดแผนการที่มีตารางอุณหภูมิจึงมีประสิทธิภาพมากกว่า Spool ที่กระตือรือร้นไม่ใช่ส่วนใหญ่เป็นเพียงตารางอุณหภูมิภายในใช่หรือไม่ ฉันเชื่อว่าฉันกำลังมองหาคำตอบที่มุ่งเน้นไปที่ internals ฉันสามารถดูว่าสแต็คการโทรแตกต่างกันอย่างไร แต่ไม่สามารถเข้าใจภาพรวมได้

ฉันใช้ SQL Server 2017 CU 11 ในกรณีที่มีคนต้องการทราบ นี่คือรหัสในการเติมตารางที่ใช้ในการสืบค้นด้านบน:

DROP TABLE IF EXISTS dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR;

CREATE TABLE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR (
ID BIGINT NOT NULL,
PRIMARY KEY (ID)
);

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (20000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
CROSS JOIN master..spt_values t3
OPTION (MAXDOP 1);


DROP TABLE IF EXISTS dbo.A_HEAP_OF_MOSTLY_NEW_ROWS;

CREATE TABLE dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (
ID BIGINT NOT NULL
);

INSERT INTO dbo.A_HEAP_OF_MOSTLY_NEW_ROWS WITH (TABLOCK)
SELECT TOP (1900000) 19999999 + ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

คำตอบ:


14

นี่คือสิ่งที่ผมเรียกคุ้มครองฮาโลวีนคู่มือการใช้งาน

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

เหตุใดแผนการที่มีตารางอุณหภูมิจึงมีประสิทธิภาพมากกว่า Spool ที่กระตือรือร้นไม่ใช่ส่วนใหญ่เป็นเพียงตารางอุณหภูมิภายในใช่หรือไม่

ระวิงมีลักษณะบางอย่างของตารางชั่วคราว แต่ทั้งสองไม่เทียบเท่าที่แน่นอน โดยเฉพาะอย่างยิ่งการเก็บพักเป็นหลักแถวโดยแถวแทรกเรียงลำดับโครงสร้าง B ต้นไม้ มันจะได้ประโยชน์จากการล็อคและการปรับแต่งการบันทึก แต่ไม่รองรับการปรับให้เหมาะสมกับโหลดจำนวนมากการเพิ่มประสิทธิภาพการโหลดทั้งกลุ่ม

ดังนั้นคนเรามักจะได้รับประสิทธิภาพที่ดีขึ้นโดยการแยกแบบสอบถามในลักษณะที่เป็นธรรมชาติ: การโหลดแถวใหม่ลงในตารางชั่วคราวหรือตัวแปรจำนวนมากจากนั้นทำการแทรกที่เหมาะสม (โดยไม่มีการป้องกันฮาโลวีนที่ชัดเจน) จากวัตถุชั่วคราว

การแยกนี้ยังช่วยให้คุณมีอิสระมากขึ้นในการปรับแต่งส่วนการอ่านและเขียนของข้อความต้นฉบับแยกต่างหาก

ในฐานะที่เป็นหมายเหตุด้านมันเป็นที่น่าสนใจที่จะคิดเกี่ยวกับวิธีการแก้ไขปัญหาวันฮาโลวีนอาจจะใช้รุ่นแถว บางที SQL Server เวอร์ชันในอนาคตอาจมีคุณสมบัตินั้นในสถานการณ์ที่เหมาะสม


ในขณะที่ Michael Kutz พูดพาดพิงถึงความคิดเห็นคุณสามารถสำรวจความเป็นไปได้ของการใช้ประโยชน์จากการเพิ่มประสิทธิภาพการเจาะรูเพื่อหลีกเลี่ยง HP ที่ชัดเจน วิธีหนึ่งที่จะบรรลุเป้าหมายนี้สำหรับการสาธิตคือการสร้างดัชนีที่ไม่ซ้ำกัน (คลัสเตอร์หากคุณต้องการ) ในคอลัมน์IDA_HEAP_OF_MOSTLY_NEW_ROWS

CREATE UNIQUE INDEX i ON dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (ID);

ด้วยการรับประกันในสถานที่เครื่องมือเพิ่มประสิทธิภาพสามารถใช้การเติมหลุมและการแบ่งปัน rowset:

MERGE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (SERIALIZABLE) AS HICETY
USING dbo.A_HEAP_OF_MOSTLY_NEW_ROWS AS AHOMNR
    ON AHOMNR.ID = HICETY.ID
WHEN NOT MATCHED BY TARGET
THEN INSERT (ID) VALUES (AHOMNR.ID);

ผสานแผน

ในขณะที่น่าสนใจคุณจะยังสามารถบรรลุประสิทธิภาพที่ดีขึ้นในหลาย ๆ กรณีโดยใช้การป้องกันฮาโลวีนแบบแมนนวล


5

หากต้องการขยายคำตอบของ Paul เล็กน้อยส่วนหนึ่งของความแตกต่างในเวลาที่ผ่านไประหว่างสปูลและตารางเทมเปอร์นั้นดูเหมือนว่าจะลดลงเนื่องจากขาดการสนับสนุนสำหรับ DML Request Sortตัวเลือกในแผนสปูล ด้วยแฟล็กการติดตามที่ไม่มีเอกสาร 8795 เวลาที่ผ่านไปสำหรับวิธี temp table จะกระโดดจาก 4400 ms เป็น 5600 ms

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1, QUERYTRACEON 8795);

โปรดทราบว่านี่ไม่เท่ากับการแทรกที่ดำเนินการโดยแผนสปูล แบบสอบถามนี้เขียนข้อมูลมากขึ้นไปยังบันทึกธุรกรรม

เอฟเฟกต์เดียวกันนี้สามารถเห็นได้ในสิ่งที่ตรงกันข้ามกับกลอุบาย เป็นไปได้ที่จะสนับสนุนให้ SQL Server ใช้การเรียงลำดับแทนที่จะเป็นสปูลสำหรับ Halloween Protection การติดตั้งครั้งเดียว:

INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (987654321) 
maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
    SELECT 1
    FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
    WHERE maybe_new_rows.ID = halloween.ID
)
ORDER BY maybe_new_rows.ID, maybe_new_rows.ID + 1
OPTION (MAXDOP 1, QUERYTRACEON 7470, MERGE JOIN);

ตอนนี้แผนมีตัวดำเนินการเรียงลำดับ TOP N แทนที่สปูล การเรียงลำดับเป็นตัวดำเนินการบล็อกดังนั้นจึงไม่จำเป็นต้องใช้สปูลอีกต่อไป:

ป้อนคำอธิบายรูปภาพที่นี่

ที่สำคัญตอนนี้เราได้รับการสนับสนุนจาก DML Request Sortตัวเลือกดูสถิติเวลาจริงอีกครั้งตัวดำเนินการแทรกตอนนี้ใช้เวลาเพียง 1623 มิลลิวินาที แผนทั้งหมดใช้เวลาประมาณ 5400 มิลลิวินาทีในการดำเนินการโดยไม่ต้องร้องขอแผนจริง

ดังที่ Hugo อธิบายผู้ประกอบการ Eager Spool รักษาความสงบเรียบร้อย ที่สามารถมองเห็นได้ง่ายที่สุดด้วยTOP PERCENTแผน เป็นเรื่องน่าเสียดายที่แบบสอบถามต้นฉบับที่มีสปูลไม่สามารถใช้ประโยชน์จากลักษณะที่เรียงลำดับของข้อมูลในสปูลได้ดีขึ้น

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