TinyIntのSQLサーバーストレージ


12

SQL Serverでは、tinyintが9Bの行に格納されているのはなぜですか。何らかの理由で、NULLビットマップマスクの最後に追加の1バイトがあるようです。

    tempdbを使用します。
    行く

    CREATE TABLE TBL
    (
        i TINYINT NOT NULL
    );
    行く

    tblに挿入(i)
        値(1);
    行く

    DBCC IND( 'tempdb'、 'tbl'、-1);
    行く

    DBCC TRACEON(3604); -ページダンプはコンソールに移動します
    行く

    DBCC PAGE( 'tempdb'、1,168,3);
    行く

結果(DBCC PAGEの最下位バイトが最初に表示されるため、バイトを反転しました):

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つのバイトではありません...
アーロン・ベルトラン

これは教育的です。私の次のSQLSaturdayの講演はcompressinについてです。そのため、データタイプの選択の意味を人々が理解し、すべてのデータタイプに対する圧縮の影響を示すために、すべてのデータタイプの例を作成しました。
ooutwire

私は、tinyintが1B(つまり)として格納され、7Bのオーバーヘッドがあると想定しました。レコードの最後に余分なバイトがあるのだろうか?
ooutwire

TINYINT列がテーブル内の唯一の列ではない場合、さまざまな結果が表示されます(期待どおりかどうかはわかりませんが)。非常にまれなユースケースのようです。
アーロンバートランド

確かにユースケースの一般的な懸念ではありません。ストレージにかかるオーバーヘッドコストと、ページ上の列の外観を初心者に見せるために、各データタイプを単独で表示しようとしていました。余分なバイトを持っているのは奇妙に思えます...そこにそれを見て、理由もなく私に夢中にさせます。
ooutwire

回答:


12

単純なサイズの追加を使用してレコードを計算すると、実際には8が得られます:4 + 1 + 2 + 1(ヘッダー+固定サイズ+ nullビットマップカウント+ nullビットマップ自体)。ただし、ヒープレコードは転送スタブサイズ(9バイト)より小さくすることはできません。これは、レコードが転送スタブに置き換えられることを保証する必要あるためです。したがって、レコードは実際には9バイトになります。A smallintは、計算サイズと最小サイズの両方で9バイトになります。大きいものはすべて転送スタブよりも大きいため、計算サイズはレコードサイズと一致します。


9バイトはこの定義にも適用されるCREATE TABLE tbl (i TINYINT NOT NULL PRIMARY KEY)ので、ヒープの一部であるかどうかに関係なく、すべての行の一般的なルールですか?
マーティンスミス

1
Bツリーはヒープ(alter table ... drop constraint)に変換でき、操作は完全な再構築ではありません(Bツリーの上位ページ破棄され、残ったリーフページはリンク解除され、結果ヒープになります)。 。
レムスルサヌ

私は、これはレムスが...述べているかを証明していると思いますimprove.dk/archive/2011/06/07/...を
ooutwire

6

著者の耳を持っていることは素晴らしいことです。:-) Kalenは、これはある種の最小行長の単なる強制であり、9未満のものは9にパディングされると疑っています。もちろん、これが可能なケースはごくわずかです。このファントムバイトは、TINYINTとBIT、およびVARCHAR(1)/ CHAR(1)に対応しています。SMALLINTまたはCHAR(2)に移動しても9を超えて増加することはありませんが、たとえばCHAR(3)に移動すると増加します。

したがって、基本的に、データ型を賢明に選択することで得られる効率を指摘できますが、ストレージレイヤーの他の要因のためにルールが成立しないエッジケースがあることを指摘します。

編集より具体的な情報をお届けしたいと思います。これは、Internalsの本の著​​者が現在考えていることであることを知らせたいだけです。彼女は100%確実ではありません。


アーレン、カレンに手を差し伸べてくれてありがとう。私は昨夜その本を掘り下げ、髪を引き抜いていた。これはsql_variantの追加のメタデータバイトと似ていますが、ここでは、手を振って「それがパルです!」と叫ぶためのファントムバイトの保存について説明する方法がありません。
ooutwire

1
そのコメントを「これは極端なケースです。これは、各行に単一のtinyintまたはchar(1)を格納しようとするテーブルが多くないためです。」
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.