เหตุใดพื้นที่ข้อมูลของตารางจึงอาจมีขนาดเท่ากับข้อมูลดิบถึง 4x


18

ฉันมีตารางที่มีแถว 490 M และพื้นที่ตาราง 55 GB ดังนั้นประมาณ 167 ไบต์ต่อแถว ตารางมีสามคอลัมน์: กVARCHAR(100)เป็นและDATETIME2(0) SMALLINTความยาวเฉลี่ยของข้อความในVARCHARฟิลด์คือประมาณ 21.5 ดังนั้นข้อมูลดิบควรอยู่ที่ประมาณ 32 ไบต์ต่อแถว: 22 + 2 สำหรับVARCHAR, 6 สำหรับDATETIME2, และ 2 สำหรับจำนวนเต็ม 16 บิต

โปรดทราบว่าพื้นที่ด้านบนเป็นข้อมูลเท่านั้นไม่ใช่ดัชนี ฉันใช้ค่ารายงานภายใต้คุณสมบัติ | จัดเก็บข้อมูล | ทั่วไป | พื้นที่ข้อมูล

แน่นอนว่าต้องมีค่าใช้จ่ายอยู่บ้างแต่ดูเหมือนว่า 135 ไบต์ต่อแถวดูเหมือนจะเยอะมากโดยเฉพาะกับโต๊ะตัวใหญ่ เหตุใดจึงเป็นเช่นนี้ มีคนอื่นเห็นตัวคูณที่เหมือนกันหรือไม่ ปัจจัยใดที่สามารถส่งผลต่อปริมาณพื้นที่เพิ่มเติมที่ต้องการ

สำหรับการเปรียบเทียบฉันพยายามสร้างตารางที่มีสองINTฟิลด์และ 1 M แถว พื้นที่ข้อมูลที่ต้องการคือ 16.4 MB: 17 ไบต์ต่อแถวเมื่อเปรียบเทียบกับข้อมูลดิบ 8 ไบต์ ตารางทดสอบอีกอันที่มีINTและที่VARCHAR(100)มีข้อความเดียวกันกับตารางจริงใช้ 39 ไบต์ต่อแถว (44 K แถว) ซึ่งฉันคาดหวังว่า 28 บวกเล็กน้อย

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

ขอบคุณล่วงหน้าสำหรับพอยน์เตอร์ใด ๆ !

แก้ไข:

NOT NULLทั้งหมดของฟิลด์ที่ระบุไว้ ตารางจริงมี PK แบบคลัสเตอร์บนVARCHARฟิลด์และDATETIME2ฟิลด์ตามลำดับนั้น สำหรับการทดสอบทั้งสองข้อแรกINTคือ PK (ทำคลัสเตอร์)

หากมีความสำคัญ: ตารางคือบันทึกผลลัพธ์การ ping ฟิลด์ต่างๆคือ URL วันที่ / เวลา ping และเวลาแฝงเป็นมิลลิวินาที ข้อมูลจะถูกผนวกอย่างต่อเนื่องและไม่อัพเดท แต่ข้อมูลจะถูกลบเป็นระยะเพื่อลดข้อมูลลงเหลือเพียงไม่กี่ระเบียนต่อชั่วโมงต่อ URL

แก้ไข:

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

คำตอบ:


11

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

ควรตรวจสอบสถานะของการแตกแฟรกเมนต์ผ่าน sys.dm_db_index_physical_stats เสมอในสถานการณ์เหล่านี้

แก้ไข: การติดตามการอัพเดทในความคิดเห็น

ความหนาแน่นของหน้าเฉลี่ย (ก่อนที่จะสร้างดัชนีคลัสเตอร์ใหม่) คือ 24% ซึ่งเหมาะอย่างยิ่งกับคำถามต้นฉบับ หน้าเว็บเต็มเพียง 1/4 ดังนั้นขนาดโดยรวมคือ 4x ขนาดข้อมูลดิบ


7

โครงสร้างบนดิสก์มีค่าใช้จ่าย:

  • ส่วนหัวของแถว
  • null บิตแมป + ตัวชี้
  • ออฟเซ็ตคอลัมน์ความยาวผันแปร
  • พอยน์เตอร์รุ่นแถว (ตัวเลือก)
  • ...

คุณมีคอลัมน์ int ขนาด 2 x 4 ไบต์

  • ส่วนหัวของแถว 4 ไบต์
  • 2 ไบต์ตัวชี้ไปยังบิตแมป NULL
  • 8 ไบต์สำหรับ 2 int คอลัมน์
  • บิตแมป NULL 3 ไบต์

ว้าว 17 ไบต์!

คุณสามารถทำแบบเดียวกันกับตารางทดสอบที่สองซึ่งมีค่าใช้จ่ายมากกว่าเดิม:

  • 2 ไบต์สำหรับจำนวนคอลัมน์ที่มีความยาวผันแปรได้
  • 2 ไบต์ต่อคอลัมน์ความยาวผันแปร

ทำไมถึงแตกต่าง นอกจากนี้ (ฉันจะไม่เชื่อมโยงกับสิ่งเหล่านี้)

  • คุณเคยสร้างดัชนีใหม่เพื่อจัดเรียงข้อมูลหรือไม่
  • การลบจะไม่เรียกคืนพื้นที่
  • หน้าข้อมูลจะแบ่งถ้าคุณแทรกเข้าไปตรงกลาง
  • การปรับปรุงอาจทำให้ตัวชี้ไปข้างหน้า (ออกจากช่องว่าง)
  • ล้นแถว
  • คอลัมน์ varchar ที่ลบโดยไม่มีการสร้างดัชนีใหม่หรือ DBCC CLEANTABLE
  • ฮีปหรือตาราง (ฮีปไม่มีดัชนีแบบคลัสเตอร์ = บันทึกกระจัดกระจายไปหมด)
  • ระดับการแยก RCSI (เพิ่ม 14 ไบต์ต่อแถว)
  • ช่องว่างต่อท้าย (SET ANSI_PADDING เปิดโดยค่าเริ่มต้น) ใน varchar ใช้ DATALENGTH เพื่อ checl ไม่ใช่ LEN
  • เรียกใช้ sp_spaceused ด้วย @updateusage = 'true'
  • ...

ดูสิ่งนี้: SQL Server: วิธีสร้างตารางที่เติมหนึ่งหน้า 8 KB?

จาก SO:


ตัวอย่างคอลัมน์ 2x4 ไบต์ไม่ถูกต้อง 100% คุณจะมีส่วนหัวของแถว 4 ไบต์ (2 สถานะไบต์และ 2 ไบต์สำหรับขนาดข้อมูลความยาวคงที่) จากนั้นคุณจะมี 2x4 ไบต์สำหรับข้อมูล สองไบต์สำหรับการนับคอลัมน์และไบต์เดียวสำหรับบิตแมป null ทำให้มีความยาวเรกคอร์ดรวม 15 ไบต์ไม่ใช่ 17
Mark S. Rasmussen

@Mark S. Rasmussen: คุณจะได้รับ "2 ไบต์สำหรับขนาดข้อมูลความยาวคงที่" ได้อย่างไร MSDN? บิตแมปที่ว่างอยู่เสมอ 3 ไบต์: sqlskills.com/blogs/paul/post/ … + msdn.microsoft.com/en-us/library/ms178085%28v=sql.90%29.aspx
gbn

ว้าวรายละเอียดดีมาก! ฉันคิดว่าฟิลด์ความยาวของVARCHARs ในการประมาณของฉันข้างต้น แต่ไม่ใช่สำหรับการนับจำนวนคอลัมน์ ตารางนี้ไม่มีเขตข้อมูล NULLable (ควรระบุว่า) มันยังคงจัดสรรจำนวนไบต์ให้หรือไม่
จอนแห่งการค้า

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

1
@gbn 2 ไบต์สำหรับขนาดข้อมูลความยาวคงที่เป็นส่วนหนึ่งของส่วนหัวของแถว 4 ไบต์ที่คุณพูดถึง นี่คือตัวชี้ที่ชี้ไปยังจุดสิ้นสุดของส่วนความยาวข้อมูลคงที่ / จุดเริ่มต้นของจำนวนคอลัมน์ / บิตแมป null บิตแมป NULL ไม่สามไบต์เสมอ หากคุณรวมจำนวนคอลัมน์มันจะต้องมีอย่างน้อยสามไบต์ แต่อาจมากกว่า - ฉันแบ่งบิตแมปและจำนวนคอลัมน์ในคำอธิบายของฉัน นอกจากนี้บิตแมป NULL ไม่เสมอไปแม้ว่ามันจะเป็นในกรณีนี้
Mark S. Rasmussen

5

ชนิดข้อมูลมีการเปลี่ยนแปลงตามเวลาหรือไม่? มีการลบคอลัมน์ที่มีความยาวผันแปรได้หรือไม่ มีการจัดเรียงดัชนีบ่อยครั้ง แต่ไม่เคยสร้างใหม่หรือไม่ มีการลบแถวจำนวนมากหรือมีคอลัมน์ที่มีความยาวผันแปรได้รับการอัปเดตอย่างมีนัยสำคัญหรือไม่ บางสนทนาที่ดีที่นี่


ฉันมั่นใจ 97% ว่าฉันไม่ได้เปลี่ยนชนิดข้อมูลหรือลบฟิลด์ ถ้าฉันทำมันคงเร็วไปกว่านี้เมื่อโต๊ะมีจำนวนแถวน้อยกว่ามาก ไม่มีการลบหรืออัปเดตข้อมูลจะถูกต่อท้ายเท่านั้น
จอนแห่งการค้า

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

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

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