วิธีการลดการกระจายตัวของฮีปใน SQL Server


10

ฉันเพิ่งพบว่าหนึ่งตารางกองมีการกระจายตัวมากกว่า 70% ดังนั้นฉันตัดสินใจที่จะทำ

ALTER TABLE dbo.myTable REBUILD

ตลกพอหลังจากนั้นฉันแยกส่วน 20% ไม่มีการเขียนบนโต๊ะนั้นตั้งแต่นั้นเป็นต้นมา ดังนั้นฉันจึงตัดสินใจที่จะสร้างใหม่อีกครั้ง

หลังจากครั้งที่ 2 หมวกตารางการกระจายตัว 50% ดังนั้นยิ่ง! ฉันไม่เข้าใจจริงๆว่ามันจะเกิดอะไรขึ้น ...


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

2
ฉันเดาว่าเราควรถามว่าโต๊ะใหญ่แค่ไหน? ในแถวและหน้า
Cody Konior

คำตอบ:


17

การกระจายตัวของสิ่งที่หมายถึงในกอง

ค่าการแตกแฟรกเมนต์ในฮีปที่คุณได้รับจากคอลัมน์avg_fragmentation_in_percentโดยการเคียวรีsys.dm_db_index_physical_statsDMV ระบุว่า

การแตกแฟรกเมนต์เชิงตรรกะสำหรับดัชนีหรือการกระจายตัวของขอบเขตสำหรับฮีปในหน่วยการจัดสรร IN_ROW_DATA

ยิ่งไปกว่านั้น BOL คนเดียวกันก็บอกว่า

นี่คือเปอร์เซ็นต์ของส่วนขยายที่ไม่อยู่ในลำดับในหน้าใบไม้ของกอง ขอบเขตที่ไม่อยู่ในลำดับคือขอบเขตที่มีหน้าปัจจุบันสำหรับฮีปนั้นไม่ได้อยู่ในขอบเขตถัดไปหลังจากขอบเขตที่มีเพจก่อนหน้า

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

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

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

ดังนั้นจึงสร้างตารางฮีปขึ้น 50 เรคคอร์ด ด้านล่างนี้เป็นลักษณะของการแตกแฟรกเมนต์หลังจากแบบสอบถาม DMV sys.dm_db_index_physical

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

คุณสามารถดูavg_fragmentation_in_percentค่าคอลัมน์ได้ 33% ตอนนี้ให้เราดูว่าหน้าจัดเรียงอย่างไร ซึ่งสามารถทำได้โดยใช้ที่ไม่มีเอกสาร%%lockres%%แบบสอบถาม แบบสอบถามจะเป็น

SELECT  %%lockres%%, * FROM dbo.HeapTest;

และด้านล่างคือผลลัพธ์ที่ดูเหมือน แนบเฉพาะส่วนที่เกี่ยวข้องเท่านั้น แบบสอบถามสร้างจำนวน 50 แถวเนื่องจากเราใส่ 50 แถวในตาราง dbo.HeapTest ของเรา

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

สิ่งที่กล่าวเป็นหน้าแรกมีรหัส197หน้าถัดไปมีรหัส242หน้าถัดไปมีรหัสอย่างต่อเนื่องจนกว่าจะถึงหมายเลขหน้าเพราะหลังจากที่เราได้รับหมายเลขหน้า264 280ดังนั้นการเพิ่มจำนวน ID หน้านี้เป็นสิ่งที่ทำให้เกิดการแตกแฟรกเมนต์

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

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

14%คุณสามารถดูการกระจายตัวอยู่ในขณะนี้

ให้เราดูการจัดสรรหมายเลขหน้า

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

เรามีการข้ามส่วนที่เหลือเพียงครั้งเดียวทุกหน้าได้รับการจัดสรร ID หน้าแบบซีเรียล เนื่องจากการกระจายตัวของกระโดดเพียงครั้งเดียวลดลงอย่างมาก

ฉันสร้าง Heap ใหม่อีกครั้งและตอนนี้เมื่อฉันตรวจสอบการแตกแฟรกเมนต์มันหายไปอย่างสมบูรณ์ และการจัดสรร ID หน้าก็เหมือนกัน

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

ทำไมการกระจายตัวเพิ่มขึ้น

ตอนนี้เกี่ยวกับสิ่งที่อาจทำให้การแตกแฟรกเมนต์เพิ่มขึ้นเราสามารถยืนยันได้ว่าเมื่อหน้าเว็บได้รับการจัดสรรไปยังฮีปพวกเขาจะไม่ต่อเนื่องดังที่คุณเห็นข้างต้นสิ่งที่ทำให้ค่าการแตกแฟรกเมนต์เพิ่มขึ้นคือ

ที่ด้านหลังของศีรษะคุณควรจำไว้ว่าคำว่าการกระจายตัวของ HEAP นั้นไม่มีความหมายใด ๆ คุณจะกำหนดความกระจัดกระจายอย่างไรสำหรับกลุ่มเพจที่ไม่ได้เรียงลำดับ

กังวลเกี่ยวกับการแยกส่วน

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

PS:โปรดอย่าใช้คำสั่งที่ไม่มีเอกสารในระบบการผลิต นี่เป็นเพียงการสาธิต


ขอขอบคุณสำหรับการวิเคราะห์โดยละเอียด ฉันกำลังเผชิญหน้ากับตารางฮีปขนาดใหญ่เพราะผู้ที่ชอบเล่น Data Vault คิดว่ามันดีกว่าการใช้ Clustered Indexes แต่จากนั้นพวกเขาใช้ข้อ จำกัด ในการตรวจสอบจำนวนมากและดัชนีที่ไม่ใช่แบบคลัสเตอร์บนฮีปเหล่านั้นดังนั้นฉันจึงไม่เห็นประโยชน์ของฮีปในสถานการณ์นี้ อย่างไรก็ตามเนื่องจากฉันเป็นเพียงนักพัฒนาที่โง่ฉันต้องจัดการกับเรื่องนี้ ขอบคุณอีกครั้งสำหรับความเข้าใจ :)
tuxmania

คุณจะเรียกใช้งาน index_type_desc, avg_fragmentation_in_percent, fragment_count, avg_page_space_used_in_percent, ผลลัพธ์จากค่าเริ่มต้น, 0, ค่าเริ่มต้นจากรายละเอียด 0, ค่า _ จาก _ sys.dm_db_index_physical_stats (db_id () หนึ่งตาราง? มันกลับมาที่ดัชนีทั้งหมดในตารางทั้งหมดสำหรับฉันแม้ว่าฉันจะแก้ไขชื่อตารางของฉันใน 'object_id'
Mickael

@Mickael ฉันได้ใช้ฟังก์ชั่น db_id () ซึ่งจะใช้ฐานข้อมูลปัจจุบันและฉันได้รับชื่อวัตถุโดยเฉพาะดังนั้นสิ่งนี้มักจะมองเข้าไปในฐานข้อมูลปัจจุบันและค้นหาHeaptestและให้ผล ฉันแน่ใจว่าคุณอาจพลาดบางสิ่ง เพียงแค่ให้แน่ใจว่าระดับความเข้ากันไม่ได้อยู่ที่ 80 ในกรณีนั้นฟังก์ชั่น db_id ไม่สามารถใช้งานได้
Shanky

@Shanky ทำไมคุณไม่แนะนำให้ใช้เคียวรีที่ไม่มีเอกสาร %% lockres %% ในการผลิต คุณช่วยอธิบายรายละเอียดได้มั้ย
Ralph

@ user1624552 เพียงเพราะมันไม่มีเอกสารหมายความว่า MS ยังไม่เก็บเอกสารเกี่ยวกับการปรับปรุง ผลกระทบหลังจากทำงานอย่างไรจะไม่ถูกบันทึกไว้ที่ใดนั่นคือสาเหตุที่มีการถาม ตัวอย่างเช่นมีคำสั่ง fn_dump_dblog () ซึ่งสร้างตัวกำหนดตารางเวลาที่ซ่อนอยู่และไม่ดี คำสั่งนี้ยังไม่ได้รับการสนับสนุน คุณสามารถใช้มันได้ แต่ความเสี่ยงนั้นขึ้นอยู่กับคุณ
Shanky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.