เมื่อตารางมีดัชนีคลัสเตอร์ดัชนีจะเป็นข้อมูลตาราง (มิฉะนั้นคุณจะมีตารางประเภทฮีป) การสร้างดัชนีคลัสเตอร์ใหม่ (ดัชนีใด ๆ ในความเป็นจริง แต่พื้นที่จะไม่ถูกนับเป็น "ข้อมูล" สำหรับดัชนีที่ไม่ได้ทำคลัสเตอร์) จะส่งผลให้หน้าเว็บที่ใช้งานบางส่วนถูกรวมเข้าเป็นรูปแบบที่สมบูรณ์ยิ่งขึ้น
ในขณะที่คุณแทรกข้อมูลลงในดัชนี (จัดเป็นคลัสเตอร์หรืออย่างอื่น) ในหน้าใบสั่งดัชนีจะถูกสร้างขึ้นตามต้องการและคุณจะมีเพียงบางส่วนเท่านั้น: หน้าสุดท้าย ในขณะที่คุณป้อนข้อมูลออกจากการจัดทำดัชนีหน้าจะต้องแยกเพื่อให้ข้อมูลพอดีในสถานที่ที่เหมาะสม: คุณจบลงด้วยสองหน้าซึ่งเต็มประมาณครึ่งหนึ่งและแถวใหม่จะเข้าสู่หนึ่งในพวกเขา เมื่อเวลาผ่านไปสิ่งนี้อาจเกิดขึ้นได้มากการใช้พื้นที่จำนวนมากพอสมควรถึงแม้ว่าเม็ดมีดในอนาคตจะเติมเต็มช่องว่างบางส่วน เพจที่ไม่ใช่ไฟล์ใบไม้จะเห็นผลกระทบที่คล้ายกันเช่นกัน แต่หน้าข้อมูลจริงนั้นมีขนาดที่ใหญ่กว่ามาก
การลบอาจส่งผลให้หน้าบางส่วน หากคุณลบแถวทั้งหมดในหน้ามันจะถูกนับเป็น "ไม่ได้ใช้" แต่ถ้ามีข้อมูลอย่างน้อยหนึ่งแถวก็จะยังคงถูกนับว่าใช้งานอยู่ แม้ว่าจะมีเพียงหนึ่งแถวที่ใช้ 10 ไบต์ในหน้าเพจนั้นจะนับเป็น 8192 ไบต์ในจำนวนพื้นที่ที่ใช้ เม็ดมีดในอนาคตอาจเติมเต็มช่องว่างบางส่วน
สำหรับแถวที่มีความยาวแปรผันการอัพเดตสามารถมีเอฟเฟ็กต์เหมือนกัน: เมื่อแถวเล็กลงมันอาจปล่อยให้พื้นที่ในหน้านั้นไม่สามารถนำมาใช้ใหม่ได้ในภายหลังและถ้าแถวในเกือบเต็มหน้ายาวขึ้น .
SQL Server ไม่ใช้เวลาในการพยายามทำให้ข้อมูลเป็นมาตรฐานโดยการจัดเรียงหน้าเว็บใหม่จนกว่าจะมีการแจ้งให้ทราบอย่างชัดเจนเช่นคำสั่งการสร้างดัชนีใหม่ของคุณเนื่องจากแบบฝึกหัดการเก็บขยะอาจเป็นฝันร้ายของประสิทธิภาพ
ฉันสงสัยว่านี่คือสิ่งที่คุณเห็นแม้ว่าฉันจะบอกว่ามีการจัดสรรพื้นที่เพียงพอสำหรับ ~ 2.7 เท่าของจำนวนข้อมูลที่ต้องใช้จริง ๆ เป็นกรณีที่ไม่ดีโดยเฉพาะ อาจหมายความว่าคุณมีบางสิ่งที่สุ่มเป็นหนึ่งในกุญแจสำคัญในดัชนี (อาจเป็นคอลัมน์ UUID) ซึ่งหมายความว่าแถวใหม่ไม่น่าจะถูกเพิ่มเข้ามาตามลำดับดัชนีและ / หรือมีการลบจำนวนมากเกิดขึ้นเมื่อเร็ว ๆ นี้
ตัวอย่างการแบ่งหน้า
การแทรกในดัชนีโดยมีแถวที่มีความยาวคงที่โดยที่แถวทั้งสี่นั้นพอดีกับหน้า:
Start with one empty page:
[__|__|__|__]
Add the first item in index order:
[00|__|__|__]
Add the next three
[00|02|04|06]
Adding the next will result in a new page:
[00|02|04|06] [08|__|__|__]
And so on...
[00|02|04|06] [08|10|12|14] [16|18|__|__]
ตอนนี้สำหรับการเพิ่มแถวออกจากดัชนี (นี่คือเหตุผลที่ฉันใช้ตัวเลขคู่ด้านบนเท่านั้น): การเพิ่ม11
อาจหมายถึงการขยายหน้าสอง (ไม่สามารถทำได้เนื่องจากมีขนาดคงที่) ย้ายทุกอย่างที่สูงกว่า 11 ขึ้นไป (แพงเกินไป ดัชนีขนาดใหญ่) หรือแบ่งหน้าดังนี้:
[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]
จากที่นี่การเพิ่ม13
และ17
จะไม่ส่งผลให้มีการแยกเนื่องจากมีห้องพักในหน้าเว็บที่เกี่ยวข้อง:
[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]
แต่เพิ่ม 03 จะ:
[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]
อย่างที่คุณเห็นหลังจากการแทรกเหล่านั้นขณะนี้เรามีหน้าข้อมูล 5 หน้าซึ่งสามารถรวมได้ทั้งหมด 20 แถว แต่เรามีเพียง 14 แถวเท่านั้น ("สิ้นเปลือง" 30% ของพื้นที่)
การสร้างใหม่ด้วยตัวเลือกเริ่มต้น (ดูด้านล่างเกี่ยวกับ "ปัจจัยการเติม") จะส่งผลให้:
[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]
บันทึกหนึ่งหน้าในตัวอย่างง่ายๆนี้ มันง่ายที่จะดูว่าการลบจะมีผลคล้ายกันกับการแทรกออกนอกดัชนีได้อย่างไร
การบรรเทา
หากคุณคาดหวังว่าข้อมูลจะอยู่ในลำดับที่ค่อนข้างสุ่มตามลำดับของดัชนีคุณสามารถใช้FILLFACTOR
ตัวเลือกเมื่อสร้างหรือสร้างดัชนีขึ้นใหม่เพื่อบอก SQL Server ให้ปล่อยช่องว่างปลอมในภายหลัง - ลดการแบ่งหน้าในระยะยาว ใช้พื้นที่มากขึ้นในตอนแรก การได้รับคุณค่านี้ผิดจะทำให้สิ่งต่าง ๆ แย่ลงแทนที่จะทำให้สถานการณ์ดีขึ้นดังนั้นจัดการด้วยความระมัดระวัง
การแยกหน้าโดยเฉพาะอย่างยิ่งในดัชนีคลัสเตอร์สามารถมีความหมายด้านประสิทธิภาพสำหรับการแทรก / การปรับปรุงดังนั้นFILLFACTOR
บางครั้งอาจถูกปรับเปลี่ยนด้วยเหตุผลนั้นแทนที่จะเป็นปัญหาการใช้พื้นที่ในฐานข้อมูลที่เห็นกิจกรรมการเขียนจำนวนมาก (แต่สำหรับแอปส่วนใหญ่ โดยคำสั่งหลายขนาดคุณโดยทั่วไปจะดีกว่าออกจากปัจจัยการเติมที่ 100% ยกเว้นกรณีเฉพาะเช่นที่คุณมีดัชนีเหนือคอลัมน์ที่มีเนื้อหาแบบสุ่มได้อย่างมีประสิทธิภาพ)
ฉันถือว่า DB ชื่อใหญ่อื่น ๆ มีตัวเลือกที่คล้ายกันหากคุณต้องการระดับการควบคุมในพวกเขาด้วย
ปรับปรุง
เกี่ยวกับALTER INDEX
คำสั่งที่เพิ่มลงในคำถามหลังจากที่ฉันเริ่มพิมพ์ข้างต้น: ฉันคิดว่าตัวเลือกจะเหมือนกับเมื่อดัชนีถูกสร้างขึ้นครั้งแรก (หรือสร้างใหม่ล่าสุด) แต่ถ้าไม่ใช่ตัวเลือกการบีบอัดอาจมีความสำคัญมากถ้ามันถูกเพิ่ม เวลาประมาณ นอกจากนี้ในคำสั่งนั้นสารเติมแต่งถูกตั้งค่าเป็น 85% ไม่ใช่ 100% ดังนั้นแต่ละหน้าใบจะว่างเปล่า ~ 15% ทันทีหลังจากการสร้างใหม่