SQL Server ที่เก็บข้อมูลของ TinyInt


12

ใน SQL Server เหตุใดจึงมีขนาดเล็กเก็บไว้กับ 9B ในแถว ด้วยเหตุผลบางอย่างดูเหมือนว่าจะมีหนึ่งไบต์เพิ่มเติมในตอนท้ายของรูปแบบบิตแมป NULL

    ใช้ tempdb;
    ไป

    สร้างตาราง tbl
    (
        ฉัน TINYINT ไม่เป็นโมฆะ
    );
    ไป

    ใส่เข้าไปใน tbl (i)
        ค่า (1);
    ไป

    DBCC IND ('tempdb', 'tbl', - 1);
    ไป

    TRACEON DBCC (3604); - ดัมพ์เพจจะไปที่คอนโซล
    ไป

    หน้า DBCC ('tempdb', 1,168,3);
    ไป

ผลลัพธ์ (ฉันย้อนกลับไบต์เนื่องจากหน้า DBCC แสดงไบต์ที่สำคัญน้อยที่สุดก่อน):

Record Size = 9B
10000500 01010000 00
TagA = 0x10 = 1B
TagB = 0x00 = 1B
Null Bitmap Offset = 0x0005 = 2B
Our integer column = 0x01 = 1B
Column Count = 0x0001 = 2B
NULL Bitmap = 0x0000 = 2B (what!?)

1
นี่เป็นเพียงการศึกษาหรือไม่? ฉันทั้งหมดสำหรับการตัดแต่งพื้นที่ที่จำเป็น แต่นี่อาจไม่ใช่ 1 byte ฉันจะเป็นห่วงเกี่ยวกับ ...
Aaron Bertrand

นี่คือการศึกษา การพูด SQLSaturday ครั้งต่อไปของฉันอยู่ที่ compressin ดังนั้นฉันได้สร้างตัวอย่างสำหรับทุกประเภทข้อมูลเพื่อช่วยให้ผู้คนเข้าใจถึงความหมายของตัวเลือกประเภทข้อมูลของพวกเขาและเพื่อแสดงผลกระทบของการบีบอัดข้อมูลทุกประเภท
ooutwire

ฉันสันนิษฐานว่า Tinyint จะถูกเก็บไว้เป็น 1B (เป็น) โดยมีค่าใช้จ่าย 7B ฉันสงสัยว่าไบต์พิเศษคืออะไรในตอนท้ายของการบันทึก ???
ooutwire

ฉันเห็นผลลัพธ์ที่แตกต่างกัน (แต่ไม่แน่ใจว่าพวกเขาสอดคล้องกับสิ่งที่คุณคาดหวังหรือไม่) เมื่อคอลัมน์ TINYINT ไม่ใช่คอลัมน์เดียวในตาราง ดูเหมือนว่ากรณีการใช้งานที่หายากสวย
Aaron Bertrand

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

คำตอบ:


12

ถ้าคุณคำนวณเรคคอร์ดโดยใช้การเพิ่มขนาดอย่างง่ายคุณจะได้รับ 8: 4 + 1 + 2 + 1 (ส่วนหัว + ขนาดคงที่ แต่เร็กคอร์ดฮีปไม่สามารถมีขนาดเล็กกว่าขนาดสตับส่งต่อซึ่งเป็น 9 ไบต์เนื่องจากเรคคอร์ดต้องรับประกันว่าสามารถแทนที่ด้วยสตับส่งต่อได้ ดังนั้นบันทึกจะตามจริง 9 ไบต์ A smallintจะมีขนาด 9 ไบต์โดยใช้การคำนวณและขนาดต่ำสุด สิ่งที่ใหญ่กว่านั้นมีขนาดใหญ่กว่าสตับที่ส่งต่อดังนั้นขนาดการคำนวณของคุณจึงตรงกับขนาดเรคคอร์ด


9 ไบต์ใช้กับคำจำกัดความนี้ด้วยหรือไม่CREATE TABLE tbl (i TINYINT NOT NULL PRIMARY KEY)ดังนั้นจึงเป็นเพียงกฎทั่วไปสำหรับทุกแถวไม่ว่าจะเป็นส่วนหนึ่งของฮีปหรือไม่
Martin Smith

1
b-tree สามารถเปลี่ยนเป็น heap ( alter table ... drop constraint) และการดำเนินการไม่ได้ถูกสร้างใหม่ (หน้า b-tree ด้านบนถูกโยนออกไปหน้าใบไม้ที่เหลือจะถูกยกเลิกการเชื่อมโยงและผลลัพธ์คือ heap) ดังนั้นตรรกะการสำรองจึงยังคงมีผลอยู่ .
Remus Rusanu

ผมคิดว่านี่เป็นข้อพิสูจน์สิ่งที่รีมัสได้กล่าว ... improve.dk/archive/2011/06/07/...
ooutwire

6

มันดีที่มีหูของผู้เขียน :-) Kalen สงสัยว่านี่เป็นเพียงการบังคับใช้ความยาวแถวขั้นต่ำบางประเภทซึ่งสิ่งที่ <9 มีเบาะถึง 9 แน่นอนมีเพียงไม่กี่กรณีที่เป็นไปได้ คุณจะพบ phantom byte นี้สำหรับ TINYINT และ BIT รวมถึง VARCHAR (1) / CHAR (1) มันจะไม่เพิ่มขึ้นเกิน 9 ถ้าคุณย้ายไปที่ SMALLINT หรือ CHAR (2) แต่จะเพิ่มขึ้นถ้าคุณย้ายไปพูด CHAR (3)

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

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


ขอบคุณแอรอนที่เอื้อมมือไปหา Kalen เมื่อคืนฉันขุดหนังสือเล่มนั้นแล้วดึงผมออกมา นี่เป็นเหมือน metadata bytes พิเศษสำหรับ sql_variant ยกเว้นที่นี่ฉันไม่มีวิธีที่จะอธิบาย phantom byte save สำหรับโบกมือและตะโกน "นั่นคือวิธีที่มันเป็นเพื่อนกัน!"
ooutwire

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