สร้างใหม่ในดัชนีคลัสเตอร์ทำไมชุดข้อมูลย่อขนาด


10

เมื่อเราทำการสร้างใหม่ในดัชนีคลัสเตอร์บนตารางที่มีข้อมูลประมาณ 15gb ในนั้นและ datasize หดเป็น 5gb สิ่งนี้จะเป็นอย่างไร "data" ประเภทใดที่ถูกลบออกไป?

ขนาดข้อมูล i หมายถึงคอลัมน์ "data" ของ DBCC sp_spaceused

ก่อนสร้างใหม่บนดัชนีคลัสเตอร์:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    39169656 KB 15857960 KB 22916496 KB 395200 KB

หลังจากสร้างใหม่บนดัชนีคลัสเตอร์:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    29076736 KB 5867048 KB  22880144 KB 329544 KB

TSQL เพื่อสร้างใหม่:

USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO

คุณกำลังกำหนดขนาดข้อมูลจากขนาดไฟล์หรือไม่?
JNK

ขนาดข้อมูลฉันหมายถึงคอลัมน์ "data" ของ DBCC sp_spaceused
Daniel Björk

ที่จะเป็น "ข้อมูล" EXEC sp_spaceusedคอลัมน์
RLF

1
ร่างกายทุกคนพลาดหรือไม่ว่า OP กำลังใช้การบีบอัดหน้า = เปิดใช้งานในสคริปต์การสร้างใหม่ของเขาและฉันคิดว่ามันไม่เคยมาก่อน Daniel ยืนยันได้ไหม
Shanky

1
@Shanky: ALTER INDEXคำสั่งนั้นดูเหมือนว่ามันถูกสร้างขึ้นโดยรหัส (เนื่องจากมีตัวเลือกมากมายในการตั้งค่าเริ่มต้น) ดังนั้นฉันสงสัยว่ามันถูกสร้างขึ้นจากตัวเลือกที่มีอยู่ของดัชนี แต่คุณถูกต้อง: หากการบีบอัดไม่ได้เปิดใช้งานในดัชนีคลัสเตอร์ก่อนที่จะมีการเรียกใช้แล้วนั่นจะอธิบายการลดส่วนใหญ่ของข้อมูล (อีกครั้ง: Daniel คุณช่วยยืนยันทางใดทางหนึ่งได้ไหม)
David Spillett

คำตอบ:


16

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

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

การลบอาจส่งผลให้หน้าบางส่วน หากคุณลบแถวทั้งหมดในหน้ามันจะถูกนับเป็น "ไม่ได้ใช้" แต่ถ้ามีข้อมูลอย่างน้อยหนึ่งแถวก็จะยังคงถูกนับว่าใช้งานอยู่ แม้ว่าจะมีเพียงหนึ่งแถวที่ใช้ 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% ทันทีหลังจากการสร้างใหม่


2
+1 หากปัจจัยการเติมหน้าน้อยกว่า 100% ตัวอย่างเช่นหากปัจจัยการเติมหน้าเท่ากับ 50% ดัชนีคลัสเตอร์ที่สร้างขึ้นใหม่ ( ตาราง ) จะสร้างใหม่ใหญ่เป็นสองเท่าราวกับว่ามันถูกสร้างขึ้นใหม่ด้วยการเติมปัจจัย 100%
Max Vernon

6

เมื่อคุณสร้างดัชนีขึ้นใหม่มันจะวางข้อมูลทั้งหมดลงบนหน้าใหม่ สิ่งที่ฉันสงสัยว่าเกิดขึ้นคือคุณลบข้อมูลจำนวนมากก่อนที่จะสร้างใหม่เช่นลบคอลัมน์อัปเดตคอลัมน์ความกว้างตัวแปรให้มีข้อมูลน้อยลงเปลี่ยนขนาดคอลัมน์ความกว้างคงที่หรือลบแถวจำนวนมาก การดำเนินการอย่างใดอย่างหนึ่งเหล่านี้อาจทำให้มีพื้นที่ว่างจำนวนมากบนหน้าเว็บซึ่งจะไม่ถูกเรียกคืนจนกว่าจะสร้างใหม่ คอลัมน์ "data" ในsp_spaceusedไม่ได้วัดข้อมูลจริง แต่จำนวนหน้า 8K ที่ใช้ในการจัดเก็บข้อมูล ขณะนี้หน้าเหล่านั้นเต็มมากขึ้นเนื่องจากการสร้างใหม่ดังนั้นข้อมูลจำนวนเดียวกันจึงเหมาะสมกับจำนวนหน้าน้อยลง


5

sp_spaceusedขั้นตอนการเก็บไม่ได้ตรวจสอบขนาด culmulative รวมของแถวในฐานข้อมูล มันกำลังรายงานขนาดของพื้นที่ที่จัดสรรเพื่อเก็บข้อมูลนั้นในขนาดสะสมของขอบเขตที่จัดสรรสำหรับข้อมูล

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

ดังนั้นไม่ควรทิ้งข้อมูลใด ๆ แต่กระบวนการสร้างใหม่ทำให้พื้นที่ว่างซึ่งฝังอยู่ในหน้าข้อมูลพร้อมใช้งานอีกครั้ง

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