Penyimpanan SQL SERVER di TinyInt

12

Dalam SQL Server, mengapa tinyint disimpan dengan 9B di baris. Untuk beberapa alasan tampaknya ada tambahan satu byte pada akhir bitmap mask NULL.

    GUNAKAN tempdb;
    PERGILAH

    CREATE TABLE tbl
    (
        SAYA TINYINT TIDAK NULL
    );
    PERGILAH

    INSERT INTO tbl (i)
        NILAI (1);
    PERGILAH

    DBCC IND ('tempdb', 'tbl', - 1);
    PERGILAH

    DBCC TRACEON (3604); - Halaman dump akan masuk ke konsol
    PERGILAH

    HALAMAN DBCC ('tempdb', 1.168,3);
    PERGILAH

Hasil (Saya membalikkan byte karena DBCC PAGE menunjukkan byte paling signifikan pertama):

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!?)
ooutwire
sumber
1
Apakah ini hanya pendidikan? Saya siap untuk memangkas ruang jika diperlukan, tapi ini mungkin bukan 1 byte yang akan saya khawatirkan ...
Aaron Bertrand
Ini mendidik. Pembicaraan SQLSaturday saya berikutnya adalah pada kompresi; jadi, saya telah membuat contoh untuk setiap tipe data untuk membantu orang memahami implikasi pilihan tipe data mereka dan untuk menunjukkan pengaruh kompresi pada semua tipe data.
ooutwire
Saya berasumsi bahwa tinyint akan disimpan sebagai 1B (itu) dengan 7B overhead. Saya ingin tahu apa byte tambahan di akhir catatan ???
ooutwire
Saya melihat hasil yang berbeda (meskipun tidak yakin apakah mereka lebih sesuai dengan yang Anda harapkan) ketika kolom TINYINT bukan satu-satunya kolom dalam tabel. Sepertinya kasus penggunaan yang cukup langka.
Aaron Bertrand
Tentu saja bukan masalah umum dari use case. Saya hanya mencoba menunjukkan masing-masing tipe data saja untuk mengarahkan pulang baik biaya overhead yang terlibat dalam penyimpanan dan untuk membiarkan pemula melihat seperti apa kolom pada halaman. Saya merasa aneh memiliki byte tambahan ... membuat saya gila untuk melihatnya di sana dan tanpa alasan.
ooutwire

Jawaban:

12

Jika Anda menghitung catatan menggunakan penambahan ukuran sederhana Anda memang mendapatkan 8: 4 + 1 + 2 + 1 (header + ukuran tetap + jumlah bitmap nol + bitmap nol itu sendiri). Tetapi catatan tumpukan tidak boleh lebih kecil dari ukuran rintisan penerusan , yaitu 9 byte, karena catatan harus menjamin bahwa itu dapat diganti dengan rintisan penerusan. Oleh karena itu, catatan akan benar-benar 9 byte. A smallintakan menjadi 9 byte baik dengan cara menghitung dan ukuran min. Apa pun yang lebih besar sudah lebih besar daripada rintisan penerusan, sehingga ukuran komputasi Anda cocok dengan ukuran rekaman.

Remus Rusanu
sumber
9 byte juga berlaku untuk definisi ini CREATE TABLE tbl (i TINYINT NOT NULL PRIMARY KEY)jadi apakah itu hanya aturan umum untuk semua baris apakah mereka merupakan bagian dari heap?
Martin Smith
1
Pohon-b dapat ditransformasikan menjadi heap ( alter table ... drop constraint) dan operasinya bukan pembangunan kembali penuh (halaman atas b-tree dibuang, halaman daun dibiarkan tidak terhubung dan hasilnya adalah tumpukan) sehingga logika reservasi masih berlaku .
Remus Rusanu
Saya pikir ini membuktikan apa Remus telah menyatakan ... improve.dk/archive/2011/06/07/...
ooutwire
6

Sangat menyenangkan memiliki telinga penulis. :-) Kalen menduga ini hanya penegakan semacam panjang baris minimum, di mana apa pun <9 diisi hingga 9. Tentu saja hanya ada beberapa kasus di mana ini mungkin. Anda akan menemukan byte hantu ini untuk TINYINT dan BIT serta VARCHAR (1) / CHAR (1). Ini tidak akan meningkat melebihi 9 jika Anda pindah ke SMALLINT atau CHAR (2), tetapi itu akan meningkat jika Anda pindah ke, katakanlah, CHAR (3).

Jadi pada dasarnya Anda bisa menunjukkan efisiensi yang bisa Anda peroleh dengan memilih tipe data dengan bijak, tetapi tunjukkan bahwa ada beberapa kasus tepi di mana aturan tidak berlaku karena faktor lain di lapisan penyimpanan.

EDIT Saya berharap memiliki informasi yang lebih nyata untuk Anda. Hanya ingin memberi tahu Anda bahwa inilah yang dipikirkan oleh penulis buku Internal saat ini. Dia tidak 100% yakin.

Aaron Bertrand
sumber
Terima kasih Aaron untuk menjangkau Kalen. Saya menggali buku itu semalam dan menarik rambut saya. Ini agak seperti byte metadata tambahan untuk sql_variant kecuali di sini saya tidak punya cara untuk menjelaskan save byte phantom untuk melambaikan tangan dan berteriak, "Begitulah sobat!"
ooutwire
1
Yah Anda dapat memasangkan komentar itu dengan "ini adalah kasus tepi ekstrem, karena tidak banyak tabel yang dirancang untuk mencoba menyimpan satu tinyint atau char (1) di setiap baris."
Aaron Bertrand