การปรับปรุงดัชนีที่ไม่ซ้ำกันและเคาน์เตอร์แก้ไขแถวสถิติ


14

รับตารางต่อไปนี้ดัชนีคลัสเตอร์ที่ไม่ซ้ำกันและสถิติ:

CREATE TABLE dbo.Banana
(
    pk integer NOT NULL, 
    c1 char(1) NOT NULL, 
    c2 char(1) NOT NULL
);

CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);

CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);

INSERT dbo.Banana 
    (pk, c1, c2) 
VALUES 
    (1, 'A', 'W'), 
    (2, 'B', 'X'), 
    (3, 'C', 'Y'), 
    (4, 'D', 'Z');

-- Populate statistics
UPDATE STATISTICS dbo.Banana;

ตัวอย่างข้อมูล

เคาน์เตอร์การปรับเปลี่ยนแถวสถิติแสดงให้เห็นชัดเจนก่อนการอัพเดทใด ๆ :

-- Show statistics modification counters
SELECT
    stats_name = S.[name], 
    DDSP.stats_id,
    DDSP.[rows],
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.object_id, S.stats_id) AS DDSP
WHERE
    S.[object_id] = OBJECT_ID(N'dbo.Banana', N'U');

ศูนย์ปรับเปลี่ยนเคาน์เตอร์

การเพิ่มpkค่าแต่ละคอลัมน์ทีละหนึ่งสำหรับทุกแถว:

-- Increment pk in every row
UPDATE dbo.Banana 
SET pk += 1;

ใช้แผนการดำเนินการ:

แผนการดำเนินการแยกเรียงยุบ

มันสร้างเคาน์เตอร์แก้ไขสถิติต่อไปนี้:

ตัวดัดแปลงการปรับปรุงภายหลัง

คำถาม

  1. ตัวดำเนินการแยกเรียงลำดับและยุบทำอะไร
  2. ทำไมpkสถิติแสดงการปรับเปลี่ยน 2 ครั้ง แต่c1และc2แสดง 5

คำตอบ:


15

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

pk = pk + 0

UPDATE dbo.Banana SET pk = pk + 1;

pk = pk + 1

UPDATE dbo.Banana SET pk = pk + 2;

pk = pk + 2

UPDATE dbo.Banana SET pk = pk + 3;

pk = pk + 3

UPDATE dbo.Banana SET pk = pk + 4; -- No overlap

pk = pk + 4

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