问题 SQL Server可以为空的数据类型大小


Microsoft SQL Server DBMS中可空数据类型的大小是多少? 

例如,非可空int应该占用4个字节,可空列的专用空间是多少?

子问题:nullable int,char(N),nvarchar(N) - 我假设它们可能以不同方式存储。

我读过的内容:

  • 在哪里可以找到SQL Server数据类型的大小  - 获取我的SQL Server版本的sql类型列表及其大小的好方法。但是没有说可空类型。
  • http://msdn.microsoft.com/en-us/library/ms189124.aspx  - 有用于计算所需的可变大小的列空间中的公式:“Variable_Data_Size = 2 +(Num_Variable_Cols×2)+ Max_Var_Size”。这是很奇怪:为什么它含有* 2倍乘数(没有告诉nvarchar的 - 这个公式是所有可变大小类型,来自说明);它必须是一个错字,Max_Var_Size被添加而不是相乘;最后它包含+2个字节用于存储值的长度,但同样不包含任何用于存储NULL值的内容。据我所知,这是可能使用的值长度的3位剩余2个字节来存储NULL标识,但它确实以这种方式存储?
  • SQL Server中“Null”值的大小  - 至于我,最热门的答案令人困惑。 @马克Byers的说“如果该字段为固定宽度存储NULL采用相同的空间的任何其它值 - 该字段的宽度”,但它不可能存储呈相同的计数的标准整数值的时间间隔和附加NULL值位。那么,“如果该字段为可变宽度的NULL值不占用空间” - 再次存储NULL不能采取任何空间都 - 它必须存储空值一些标记。与其他答案类似的混淆:有人说它需要2个额外的字节,有人 - 只有1个字节。
  • http://home.clara.net/drdsl/MSSQL/DataTypes.html  - 具有类型大小的漂亮表,但同样没有专用于NULL值的表。

11277
2018-01-13 18:20


起源



答案:


可以为空的列和不可为空的列占用 一模一样 存储在数据页面上。每个数据页的一部分是空位映射,它有一个位 一切 表中的列,甚至是不可为空的列。

一种常见的误解是数据页的空位映射部分仅存储可空列的位。这不是真的。 null-bit-map部分包含可为空的标志 所有 表中的列。 这里 是解释这个神话的好参考。 这里 是另一个。

我想知道为什么SQL Server(以及之前的Sybase)使用这种结构。一种可能性是改变柱的可空性可以是“快速”操作。虽然所有页面都有很大的变化,但是通过引入新的NULLable字段没有页面拆分的危险。

另一种可能性是它将页面上的布局与表元数据分离。虽然页面不知道列名,但它确实知道基于列索引的列的所有内容。


7
2018-01-13 21:08





根据Microsoft支持

  1. SQL Server 2008中的NULL值:

    - SPARSE需要额外增加6个字节的行大小+每个非空列4个字节+值的字节数(类型无关紧要)
    - NULL位图中的常规NULL值需要1位

  2. SQL Server 2008中的空字符串:

    - 即使输入空字符串,固定长度数据也需要数据的完整空间 - 可变长度数据需要2个字节的开销来存储数据 - 数值上没有空字符串 - NULL值在NULL位图中需要1位

参考: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/0404de89-70dc-4026-9e2e-13ddc3e7c058/null-data-storage-sql-server-2008?forum=sqldatabaseengine


4
2018-01-13 18:38



很好的链接,谢谢。这是我第一次听说稀疏列=)。我不确定你能证实,但它真的是一个额外的位,还是它占据了整个字节?因为SQL Server中的位数据类型实际使用1个字节。 - Oleksandr Pshenychnyy
顺便说一句,对于稀疏列,请考虑 这个部分 按数据类型估算的空间节省量。 - OzrenTkalcecKrznaric
@OleksandrPshenychnyy - SQL Server将NULL标志位打包成一个字节,因此最多8个可空列只产生一个字节的开销。 - HABO


答案:


可以为空的列和不可为空的列占用 一模一样 存储在数据页面上。每个数据页的一部分是空位映射,它有一个位 一切 表中的列,甚至是不可为空的列。

一种常见的误解是数据页的空位映射部分仅存储可空列的位。这不是真的。 null-bit-map部分包含可为空的标志 所有 表中的列。 这里 是解释这个神话的好参考。 这里 是另一个。

我想知道为什么SQL Server(以及之前的Sybase)使用这种结构。一种可能性是改变柱的可空性可以是“快速”操作。虽然所有页面都有很大的变化,但是通过引入新的NULLable字段没有页面拆分的危险。

另一种可能性是它将页面上的布局与表元数据分离。虽然页面不知道列名,但它确实知道基于列索引的列的所有内容。


7
2018-01-13 21:08





根据Microsoft支持

  1. SQL Server 2008中的NULL值:

    - SPARSE需要额外增加6个字节的行大小+每个非空列4个字节+值的字节数(类型无关紧要)
    - NULL位图中的常规NULL值需要1位

  2. SQL Server 2008中的空字符串:

    - 即使输入空字符串,固定长度数据也需要数据的完整空间 - 可变长度数据需要2个字节的开销来存储数据 - 数值上没有空字符串 - NULL值在NULL位图中需要1位

参考: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/0404de89-70dc-4026-9e2e-13ddc3e7c058/null-data-storage-sql-server-2008?forum=sqldatabaseengine


4
2018-01-13 18:38



很好的链接,谢谢。这是我第一次听说稀疏列=)。我不确定你能证实,但它真的是一个额外的位,还是它占据了整个字节?因为SQL Server中的位数据类型实际使用1个字节。 - Oleksandr Pshenychnyy
顺便说一句,对于稀疏列,请考虑 这个部分 按数据类型估算的空间节省量。 - OzrenTkalcecKrznaric
@OleksandrPshenychnyy - SQL Server将NULL标志位打包成一个字节,因此最多8个可空列只产生一个字节的开销。 - HABO