SQL Server ใช้ชุดค่าผสมแยกเรียงลำดับและยุบของตัวดำเนินการทุกครั้งเมื่อรักษาดัชนีที่ไม่ซ้ำกันไว้เป็นส่วนหนึ่งของการปรับปรุงที่มีผลกระทบ (หรืออาจมีผลต่อ) มากกว่าหนึ่งแถว
จากตัวอย่างในคำถามเราสามารถเขียนการอัปเดตเป็นการอัปเดตแบบแถวเดี่ยวแยกสำหรับแต่ละแถวที่มีอยู่สี่แถว:
-- Per row updates
UPDATE dbo.Banana SET pk = 2 WHERE pk = 1;
UPDATE dbo.Banana SET pk = 3 WHERE pk = 2;
UPDATE dbo.Banana SET pk = 4 WHERE pk = 3;
UPDATE dbo.Banana SET pk = 5 WHERE pk = 4;
ปัญหาคือว่าคำสั่งแรกจะล้มเหลวเนื่องจากมันเปลี่ยนpk
จาก 1 เป็น 2 และมีแถวที่pk
= 2 เอ็นจิ้นการจัดเก็บ SQL Server ต้องการดัชนีเฉพาะที่ยังคงไม่ซ้ำกันในทุกขั้นตอนของการประมวลผลแม้ในคำสั่งเดียว . นี่เป็นปัญหาที่แก้ไขได้โดยแยกเรียงลำดับและยุบ
แยก
ขั้นตอนแรกคือการแยกแต่ละคำสั่งปรับปรุงเป็นลบตามด้วยการแทรก:
DELETE dbo.Banana WHERE pk = 1;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');
DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');
DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');
DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');
ตัวดำเนินการแยกเพิ่มคอลัมน์รหัสการกระทำลงในสตรีม (ที่นี่ระบุว่า Act1007):
รหัสการกระทำคือ 1 สำหรับการอัพเดต 3 สำหรับการลบและ 4 สำหรับการแทรก
ประเภท
ข้อความสั่งแยกด้านบนจะยังคงสร้างการละเมิดคีย์ที่ไม่ซ้ำชั่วคราวชั่วคราวดังนั้นขั้นตอนต่อไปคือการจัดเรียงข้อความตามคีย์ของดัชนีที่ไม่ซ้ำที่กำลังอัปเดต ( pk
ในกรณีนี้) จากนั้นตามรหัสการกระทำ สำหรับตัวอย่างนี้หมายความว่าการลบ (3) บนคีย์เดียวกันนั้นมีการเรียงลำดับก่อนการแทรก (4) ผลลัพธ์ที่ได้คือ:
-- Sort (pk, action)
DELETE dbo.Banana WHERE pk = 1;
DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');
DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');
DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');
ล่มสลาย
ขั้นตอนก่อนหน้านี้เพียงพอที่จะรับประกันการหลีกเลี่ยงการละเมิดที่เป็นเอกลักษณ์ในทุกกรณี ในฐานะการเพิ่มประสิทธิภาพยุบรวมการลบและแทรกที่อยู่ติดกันในค่าคีย์เดียวกันในการปรับปรุง:
-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');
คู่การลบ / การแทรกสำหรับpk
ค่า 2, 3 และ 4 ถูกรวมเข้ากับการอัพเดตโดยปล่อยการลบครั้งเดียวเมื่อpk
= 1 และการแทรกสำหรับpk
= 5
ยุบกลุ่มโอเปอเรเตอร์แถวเรียงตามคอลัมน์สำคัญและอัปเดตรหัสการกระทำเพื่อสะท้อนถึงผลการยุบ:
การอัพเดตดัชนีแบบคลัสเตอร์
ตัวดำเนินการนี้มีข้อความกำกับว่าเป็นอัปเดต แต่สามารถแทรกอัปเดตและลบได้ การดำเนินการใดที่ดำเนินการโดยการอัพเดตดัชนีแบบกลุ่มต่อแถวจะถูกกำหนดโดยค่าของรหัสการกระทำในแถวนั้น ผู้ประกอบการมีคุณสมบัติการกระทำเพื่อสะท้อนถึงโหมดการทำงานนี้:
เคาน์เตอร์แก้ไขแถว
โปรดทราบว่าการอัปเดตทั้งสามรายการข้างต้นไม่ได้แก้ไขคีย์ของดัชนีที่ไม่ซ้ำซึ่งจะคงไว้ เราได้เปลี่ยนการอัปเดตเป็นคอลัมน์สำคัญในดัชนีเป็นการอัปเดตของคอลัมน์ที่ไม่ใช่คีย์ ( c1
และc2
) รวมถึงการลบและการแทรก การลบหรือการแทรกอาจทำให้เกิดการละเมิดคีย์เฉพาะที่ไม่ถูกต้อง
แทรกหรือลบส่งผลกระทบต่อทุกคอลัมน์เดียวในแถวดังนั้นสถิติที่เกี่ยวข้องกับทุกคอลัมน์จะมีการเพิ่มเคาน์เตอร์การเปลี่ยนแปลงของพวกเขา สำหรับการอัปเดตเฉพาะสถิติของคอลัมน์ที่อัปเดตใด ๆ เนื่องจากคอลัมน์นำมีตัวนับการแก้ไขเพิ่มขึ้น (แม้ว่าค่าจะไม่เปลี่ยนแปลง)
ตัวนับการแก้ไขแถวสถิติแสดงการเปลี่ยนแปลง 2 รายการpk
และ 5 สำหรับc1
และc2
:
-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1; -- All columns modified
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2; -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3; -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4; -- c1 and c2 modified
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z'); -- All columns modified
หมายเหตุ:เฉพาะการเปลี่ยนแปลงที่นำไปใช้กับวัตถุฐาน (ฮีปหรือดัชนีคลัสเตอร์) มีผลกับตัวนับการปรับเปลี่ยนแถวสถิติ ดัชนีที่ไม่ใช่คลัสเตอร์เป็นโครงสร้างรองซึ่งสะท้อนการเปลี่ยนแปลงที่ทำกับวัตถุฐานแล้ว ไม่มีผลกับตัวนับการแก้ไขแถวสถิติเลย
หากวัตถุมีดัชนีที่ไม่ซ้ำกันหลายชุดจะใช้การแยกจัดเรียงแยกและยุบเพื่อจัดระเบียบการอัปเดตให้กับแต่ละรายการ SQL Server ปรับกรณีนี้ให้เหมาะสมสำหรับดัชนีที่ไม่ได้ทำคลัสเตอร์โดยบันทึกผลลัพธ์ของการแบ่งเป็น Eager Table Spool จากนั้นเล่นซ้ำที่กำหนดไว้สำหรับแต่ละดัชนีที่ไม่ซ้ำกัน (ซึ่งจะมีการเรียงลำดับตามดัชนีคีย์
ผลต่อการอัพเดทสถิติ
การอัปเดตสถิติอัตโนมัติ (หากเปิดใช้งาน) จะเกิดขึ้นเมื่อเครื่องมือเพิ่มประสิทธิภาพการสืบค้นต้องการข้อมูลสถิติและแจ้งว่าสถิติที่มีอยู่ล้าสมัย (หรือไม่ถูกต้องเนื่องจากการเปลี่ยนแปลงสคีมา) สถิติถูกพิจารณาว่าล้าสมัยเมื่อจำนวนของการแก้ไขที่บันทึกไว้เกินขีด จำกัด
การจัดเรียงแบบแยก / เรียงลำดับ / ยุบส่งผลให้มีการปรับเปลี่ยนแถวต่างกันที่บันทึกไว้เกินกว่าที่ควรจะเป็น ในทางกลับกันหมายความว่าการอัปเดตสถิติอาจถูกกระตุ้นไม่ช้าก็เร็ว
ในตัวอย่างข้างต้นการแก้ไขแถวสำหรับคอลัมน์คีย์เพิ่มขึ้น 2 (การเปลี่ยนแปลงสุทธิ) มากกว่า 4 (หนึ่งสำหรับแต่ละแถวตารางที่ได้รับผลกระทบ) หรือ 5 (หนึ่งสำหรับแต่ละลบ / ปรับปรุง / แทรกผลิตโดยยุบ)
นอกจากนี้คอลัมน์ที่ไม่ใช่คีย์ที่ไม่มีการเปลี่ยนแปลงอย่างมีเหตุมีผลโดยแบบสอบถามดั้งเดิมจะสะสมการแก้ไขแถวซึ่งอาจมีจำนวนมากเป็นสองเท่าของแถวตารางที่อัปเดต (คอลัมน์หนึ่งสำหรับแต่ละการลบและหนึ่งคอลัมน์สำหรับแต่ละแทรก)
จำนวนการเปลี่ยนแปลงที่บันทึกไว้จะขึ้นอยู่กับระดับของการทับซ้อนระหว่างค่าคอลัมน์คีย์เก่าและใหม่ การรีเซ็ตตารางระหว่างการดำเนินการแต่ละครั้งแบบสอบถามต่อไปนี้แสดงให้เห็นถึงผลกระทบต่อตัวนับการปรับเปลี่ยนแถวที่มีการทับซ้อนที่แตกต่างกัน:
UPDATE dbo.Banana SET pk = pk + 0; -- Full overlap
UPDATE dbo.Banana SET pk = pk + 1;
UPDATE dbo.Banana SET pk = pk + 2;
UPDATE dbo.Banana SET pk = pk + 3;
UPDATE dbo.Banana SET pk = pk + 4; -- No overlap