เพราะเหตุใดฐานข้อมูลของฉันยังคงกระจัดกระจายหลังจากฉันสร้างและทำดัชนีใหม่ทุกอย่างแล้ว


40

ฉันมีฐานข้อมูลที่ฉันพยายามจัดระเบียบตารางทั้งหมดในครั้งเดียวโดยใช้ T-SQL นี้:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

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

ฉันรันสิ่งนี้เพื่อพิจารณาว่าฉันยังมีการแยกส่วน:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

และฉันได้รับ:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

ฉันรู้ว่าฉันขาดอะไรบางอย่างพื้นฐานที่แท้จริง แต่ฉันไม่รู้อะไรเลย


คุณได้รับข้อผิดพลาดอะไร นอกจากนี้ยังมีเหตุผลที่คุณมีการจัดระเบียบใหม่และสร้างสิ่งเดียวกันหรือไม่
Shawn Melton

Shawn ฉันขอโทษที่ฉันหายไปหนึ่งคำ ฉันไม่มีข้อผิดพลาด สำหรับสาเหตุที่ฉันรันทั้งสองคำสั่งฉันทำอย่างนั้นหลังจากลองแต่ละคำสั่งทีละรายการ ฉันอัพเดตคำถาม
Justin Dearing

คำตอบ:


38

ตารางมีขนาดเล็ก จำนวนหน้าในตารางของคุณคือ:

11, 8, 6, 5, 13, 8, 10

พวกเขาครอบครอง 480kb รวม ไม่มีอะไรที่จะจัดเรียงข้อมูลอย่างแท้จริง

แก้ไข: นี่รับประกันคำอธิบายเพิ่มเติมเล็กน้อย

โดยปกติแล้วตารางหรือดัชนีใหม่จะถูกจัดสรรเป็น 8 หน้าแรกจากแบบผสมมากกว่าระดับที่สม่ำเสมอ ดังนั้นจึงเป็นไปได้ที่แต่ละหน้า 8 หน้าแรกจะได้รับการจัดสรรจากขอบเขตผสมที่แตกต่างกัน ตารางหรือดัชนีที่ใช้ 8 หน้าจึงอาจมี 8 แฟรกเมนต์ 1 ในแต่ละส่วนผสมที่แตกต่างกัน 8 รายการ

สคริปต์การจัดเรียงข้อมูลที่ใช้กันอย่างแพร่หลาย (ตัวอย่างของการเชื่อมโยงด้านล่าง) มีแนวโน้มที่จะไม่รวมตารางขนาดเล็กเนื่องจากสิ่งนี้ IIRC <500 หน้าเป็นหนึ่งหรือทั้งสองอย่าง ที่ขนาดเหล่านี้มีประโยชน์น้อยมากในการจัดเรียงข้อมูลและตัวเลขการแตกแฟรกเมนต์อาจเบ้โดยการจัดสรรขอบเขตแบบผสม


ตกลงนั่นเป็นที่น่าพอใจถ้าไม่มีคนอื่นมีคำตอบที่ดีกว่าฉันจะทำเครื่องหมายของคุณว่าถูกต้อง
Justin Dearing

3
+1 เห็นด้วยกับ Mark กังวลเกี่ยวกับการแตกแฟรกเมนต์เมื่อคุณมีข้อมูลจริง :-)
Aaron Bertrand

ฉันเข้าใจสิ่งที่คุณพูด แต่จากความอยากรู้อย่างแท้จริงนี่เป็นเพราะเอ็นจิ้น db ไม่สามารถจัดเรียงข้อมูลในบางหน้าได้หรือไม่ ฉันหมายความว่าต้องมีเหตุผลสำหรับสิ่งนี้
Thomas Stringer

3
ไม่ใช่ว่ามันทำไม่ได้ แต่ทำไมมันถึงรบกวน? การทำเช่นนี้จะทำให้ไม่มีผลกระทบต่อ I / O เพียงเล็กน้อยโดยเฉพาะอย่างยิ่งเนื่องจากตารางขนาดเล็กนี้รับประกันได้ว่าจะอยู่ในความทรงจำอยู่แล้ว
Aaron Bertrand

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

18

อ้างจาก " แนวทางปฏิบัติที่ดีที่สุดสำหรับการจัดเรียงดัชนีของ Microsoft SQL Server 2000 ":

"การแตกแฟรกเมนต์ส่งผลกระทบต่อดิสก์ I / O ดังนั้นให้เน้นที่ดัชนีที่มีขนาดใหญ่กว่าเนื่องจากเพจของพวกเขามีโอกาสน้อยที่จะถูกแคชโดย SQL Server ใช้จำนวนหน้าที่รายงานโดย DBCC SHOWCONTIG เพื่อรับทราบขนาดของดัชนี (แต่ละหน้าคือ ขนาด 8 KB) โดยทั่วไปคุณไม่ควรกังวลเกี่ยวกับระดับการแตกแฟรกเมนต์ของดัชนีที่มีน้อยกว่า 1,000 หน้าในการทดสอบดัชนีที่มีมากกว่า 10,000 หน้าที่รับรู้ถึงประสิทธิภาพที่เพิ่มขึ้น มากกว่า 50,000 หน้า) "

ดังนั้นคำตอบแบบนี้จะตอบคำถามของคุณและสำรองคำตอบของมาร์กและแอรอนไว้

คุณสามารถค้นหาข้อมูลที่ดีเกี่ยวกับการกระจายตัวของดัชนีในบทความต่อไปนี้จาก Brent Ozar:

มหาสมุทร Also..an ของข้อมูลที่ดีเกี่ยวกับการจัดทำดัชนีในทั่วไป (ยังเกี่ยวกับปัญหาการกระจายตัว) สามารถพบได้บนบล็อกของคิมเบอร์ลี Tripp ของ


11

สิ่งนี้ไม่ได้มีไว้เพื่อตอบคำถามของคุณ แต่จะไม่เหมาะกับความคิดเห็น คุณสามารถสร้างสคริปต์นี้แบบไดนามิกโดยไม่ต้องคัดลอกและวางผลลัพธ์ลงในหน้าต่างอื่น คำนึงถึงว่าไม่มีเหตุผลอย่างแน่นอนREORGANIZEแล้วREBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;

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