以下所有内容均引用自此处的datetime
行。我已经打破了引用以对我的理解进行评论。
通过使用两个 4 字节整数来使用整数数据表示。整数值表示以 1900-01-01 为基准日期的天数。
换句话说,我们有八个字节可以使用。datetime
这与已经占用的内容完全相同。
前 2 个字节最多可以代表 2079 年。在此之前,压缩始终可以在此处保存 2 个字节。
换句话说,到 2079 年为止,年份都会丢失两个字节。在那之后,我们会失去更多。这意味着对于 2079 年之前的日期,我们可以使用原始八个字节中的六个。
每个整数值代表 3.33 毫秒。压缩在前五分钟内耗尽了前 2 个字节 [原文如此],并在下午 4 点后需要第四个字节。
换句话说,下午 4 点之后,我们只剩下剩余的 6 个字节中的两个可以使用。
因此,下午 4 点之后压缩只能节省 1 个字节。
这显然是我误解的部分。我之前的算术证明我们还剩两个轮空。然而,微软表示我们只有一个。这是双重令人困惑的,因为如果我们超过了 2079 年,那么微软的数字就会认为我们还剩下负 1 个字节。
当日期时间像任何其他整数一样被压缩时,压缩会在日期中节省 2 个字节。
用户无法控制压缩的工作方式,因此这一行完全无关。
从上面的内容可以看出,我的理解存在很大的误区。我错过了什么?
不关注
datetime
行压缩的文档;这是无稽之谈。我只能假设作者混淆了关于datetime
存储、内存和持久存储的几种想法。事实上,它
datetime
被压缩为单个八字节值,其中四个字节表示日期,前面四个字节表示时间部分。日期字节是有符号整数*,表示基准日期之前或之后的天数。时间字节是午夜之后的整数刻度数 (1/300 秒)。其效果是行压缩的列描述符存储
datetime
几乎完全取决于日期,而不是时间部分。时间起作用的唯一日期是基准日期“1900-01-01”,因为它在日期部分中被编码为零,并且所有这些零都可以被压缩掉。
仅该一个日期所需的物理存储就取决于对时间部分进行编码所需的字节数。对于基准日期的午夜,行压缩的存储大小通常为零。
所需的行压缩字节数
datetime
总结如下:对于最常见的
datetime
值(本来是八个字节),您可以期望节省一两个字节。例子
由于文档提到始终为 2079 年之前的日期保存两个字节,让我们看看如何存储“31 Dec 2078”:
使用
DBCC PAGE
:该日期是基准日期之后的 65,378 (0xFF62) 天。该数字不适合两个字节的有符号范围(-32,768 到 +32,767),因此需要三个字节。
三个字节可以容纳 16,777,216 个值,该范围的一半是 8,388,608。将偏差应用于天数得出 65,378 - 8,388,608 = -8,323,230 (0x80FF62)。
您可以在屏幕截图中看到编码的日期字节
80FF62
,后面跟着四个零字节的时间部分,总共提供了七个字节的行压缩存储。* 列描述符短格式仅存储正值。通过应用无符号范围一半的偏差来容纳负数。例如,在应用 128(单字节无符号范围的一半)的偏差后,单字节格式的 -1 存储为 127 (0x7f)。