SQL Serverでの「Null」値のサイズ


118

たとえば、10列の大きなテーブルがあります。それらの4つはほとんどの場合nullのままです。null値が任意のサイズまたはバイト単位のサイズをとらないクエリがあります。私はそれらのいくつかが言っているいくつかの記事を読みました:

http://www.sql-server-citation.com/2009/12/common-mistakes-in-sql-server-part-4.html

テーブルにNULL値がある場合、ストレージスペースを占有しないという誤解があります。実際、NULL値はスペースを占有します– 2バイト

SQL:NULL値とデフォルト値の使用

NULLデータベースの値は、1バイトのストレージを占めるシステム値であり、スペースやゼロなどのデフォルト値ではなく、値が存在しないことを示します。

ヌル値でとったサイズについて教えてください。

回答:


146

フィールドが固定幅の場合、NULLを格納すると、他の値と同じスペース(フィールドの幅)が使用されます。

フィールドが可変幅の場合、NULL値はスペースを占有しません。

null値を格納するために必要なスペースに加えて、null許容列を持つためのオーバーヘッドもあります。各行について、null許容列ごとに1ビットが使用され、その列の値がnullかどうかを示します。これは、列が固定長でも可変長でも同じです。


他のソースからの情報で観察された不一致の理由:

  • 最初の記事の始まりは少し誤解を招くものです。この記事では、NULL値を格納するコストについては触れていませんが、NULLを格納する機能があることのコスト(つまり、列をNULL可能にするコスト)について説明しています。列をnullにできるようにするためにストレージスペースにコストがかかるのは事実ですが、一度実行すると、値を格納するよりもNULLを格納するために必要なスペースが少なくなります(可変幅の列の場合)。

  • 2番目のリンクは、Microsoft Accessに関する質問のようです。AccessがNULLを格納する方法の詳細はわかりませんが、SQL Serverと異なっていても驚くことはありません。


1
@Mark「列をnullにできるようにするためにストレージスペースにコストがかかるのは事実ですが、一度実行すると、値を格納するよりもNULLを保存するために必要なスペースが少なくなります(可変幅の列の場合)」これはつまり、可変データ型の場合、メモリで取得されるサイズとして1ビットが必要です。
ロッキーシン

13
ほとんどのコンピュータシステムでアドレス指定可能なメモリの最小単位は1 byte(通常は8ビット)です。したがって、実際にはaにbitはが必要byteです。すばらしい答え:+1。
JohnB

20
ただし、2番目のビットと3番目のビット、および8番目のビットまでは、同じバイトに収まります。
Matti Virkkunen、2009

1
@Mark-はい、かなり明確に見えます。コメントが消えたことをお詫びします。修正するつもりでしたが、削除と送信の間にインターネット接続がダウンしました また、(ここのコメントセクションから)「ヒープおよびクラスター化インデックスレコードの場合、常にNULLビットマップがあります。非クラスター化インデックスの場合、インデックス内のすべての列がNULLでない場合はありません。」
マーティン・スミス

2
@マーティン・スミス:知らなかった。それが正しく理解できれば、列がnull可能になっても、その列がインデックスとインデックス内の他の列にもない限り、(nullビットマップが常に存在するため)必要なストレージ領域が増加しないことを意味するため、状況はさらに複雑になります。 null可能ではありません。この場合、インデックスにはnullビットマップを含める必要があります。
Mark Byers

30

列が可変長である場合、すなわち、その次のリンクを主張varchar次いでNULL0バイトをとる(プラス1バイトの値であるか否かのフラグに使用されているNULLかどうか)。

上記のリンクと以下のリンクは、固定長の列、つまりchar(10)またはintの値がNULL列の長さを占める(プラスかどうかにフラグを付けるために1バイトプラス)と主張していますNULL

例:

  1. aをに設定するchar(10)NULL、10バイトを占有します(ゼロに設定されます)。
  2. an intは4バイトを取ります(これもゼロ化されます)。
  3. 0バイトvarchar(1 million)NULL取るためのセット(+ 2バイト)

注:わずかに正接すると、ストレージサイズはvarchar入力されたデータの長さ+ 2バイトになります。


NULLを格納するvarcharは0 + 2 + 1(NULLオーバーヘッド)バイトを必要としないでしょうか?
Akash 2015

NULLフラグを付けるには、+ 1 ビットにする必要があります。@Akash:ビットマップはすでに値にNULLのフラグを立てているため、2バイトは必要ありません(情報は追加されません)。
SimoKivistö18年

5

このリンクから

各行には、NULLを許可する列のNULLビットマップがあります。その列の行がnullの場合、ビットマップのビットは1、それ以外の場合は0です。

可変サイズのデータ​​型の場合、実際のサイズは0バイトです。

固定サイズのデータ​​型の場合、実際のサイズは、デフォルト値に設定されたバイト単位のデフォルトのデータ型サイズです(数値の場合は0、文字の場合は '')。


nvarchar(max)varchar(max)のようなデータ型の場合、Nullは0バイトを使用し、int、charsなどの場合は、デフォルトサイズからデフォルト値を取得するということですか?
ロッキーシン

4

NULL値を格納しても、スペースは必要ありません。

「実際のところ、NULL値は2バイトのスペースを占有します。」

これは誤解です。つまり、1行あたり 2バイトであり、null許容列があるかどうかに関係なく、すべての行がそれらの2バイトを使用していると確信しています。

データベースのNULL値は、1バイトのストレージを占めるシステム値です

これは、特にSQL Serverではなく、データベース全般について語っています。SQL ServerはNULL値を格納するために1バイトを使用しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.