本主题总结了数据库引擎如何实现行压缩。 此摘要提供基本信息,可帮助你规划数据所需的存储空间。
启用压缩只会更改与数据类型关联的数据的物理存储格式,但不会更改其语法或语义。 启用一个或多个表进行压缩时,不需要应用程序更改。 新的记录存储格式具有以下主要更改:
它减少了与记录关联的元数据开销。 此元数据是有关列及其长度和偏移量的信息。 在某些情况下,元数据开销可能大于旧的存储格式。
它对数值类型(例如
integer
、decimal
和float
)以及基于数值的类型(例如datetime
和money
)使用可变长度存储格式。它通过使用可变长度格式存储固定的字符串,方法是不存储空白字符。
注释
所有数据类型的 NULL 值和 0 个值都经过优化,不采用任何字节。
行压缩如何影响存储
下表介绍了行压缩如何影响 SQL Server 中的现有类型。 该表不包括使用页面压缩可以实现的节省。
数据类型 | 存储是否受影响? | DESCRIPTION |
---|---|---|
tinyint |
否 | 1 字节是所需的最低存储。 |
smallint |
是的 | 如果该值适合 1 个字节,则仅使用 1 个字节。 |
int |
是的 | 仅使用所需的字节。 例如,如果一个值可以存储在 1 个字节中,则存储将只占用 1 个字节。 |
bigint |
是的 | 仅使用所需的字节。 例如,如果一个值可以存储在 1 个字节中,则存储将只占用 1 个字节。 |
decimal |
是的 | 此存储与 vardecimal 存储格式完全相同。 |
numeric |
是的 | 此存储与 vardecimal 存储格式完全相同。 |
bit |
是的 | 元数据开销使其增加到 4 位。 |
smallmoney |
是的 | 使用 4 字节整数来表示整数数据。 货币值乘以 10000,生成的整数值通过删除小数点后的任何数字来存储。 此类型具有类似于整数类型的存储优化。 |
money |
是的 | 使用8字节整数进行数据表示。 货币值乘以 10000,生成的整数值通过删除小数点后的任何数字来存储。 此类型的范围大于 smallmoney 。 此类型具有类似于整数类型的存储优化。 |
float |
是的 | 不存储具有零的最小有效字节。
float 压缩主要适用于 mantissa 中的非常数值。 |
real |
是的 | 不存储具有零的最小有效字节。
real 压缩主要适用于 mantissa 中的非常数值。 |
smalldatetime |
否 | 通过使用两个 2 字节整数来表示整数数据。 日期需要 2 个字节。 这是自 1901 年 1 月 1 日起的天数。 从 1902 年开始,这需要 2 个字节。 因此,从那时起没有节省。 时间是自午夜以来的分钟数。 刚过4AM的时间值开始使用第二个字节。 如果 a smalldatetime 仅用于表示日期(常见情况),则时间为 0.0。 压缩通过将时间存储为行压缩的最重要字节格式来节省 2 个字节。 |
datetime |
是的 | 使用两个 4 字节整数的整数表示形式。 整数值表示基准日期为 1/1/1900 的天数。 前 2 个字节最多可以表示 2079 年。 压缩始终可以在此处保存 2 个字节,直到该点为止。 每个整数值表示 3.33 毫秒。 压缩在前 5 分钟内耗尽前 2 个字节,在下午 4 点后需要第四个字节。 因此,压缩只能在下午 4 点后保存 1 个字节。
datetime 和其他整数压缩时一样,压缩在日期中节省了 2 个字节。 |
date |
否 | 使用 3 个字节的整数数据表示形式。 这表示从 0001 年 1 月 1 日起的日期。 对于当代日期,行压缩使用所有 3 个字节。 这不会节省任何费用。 |
time |
否 | 使用 3 到 6 个字节的整数数据表示形式。 从 0 到 9 开始的各种精度可能需要 3 到 6 个字节。 请注意,行压缩的存储没有变化。 总体而言,压缩time 数据类型不能期望节省太多。 压缩空间的使用如下:精度 = 0。 字节 = 3。 每个整数值表示一秒。 压缩可以表示最多 6PM 的时间,使用 2 个字节,可能会节省 1 个字节。 精度 = 1。 字节 = 3。 每个整数值表示 1/10 秒。 压缩在 2AM 之前使用第三个字节。 带来很少的节省。 精度 = 2。 字节 = 3。 与前一种情况类似,不可能实现节省。 精度 = 3。 字节数 = 4。 由于前 3 个字节被 5AM 占用,因此无法实现多少节省。 精度 = 4。 字节数 = 4。 前 3 个字节是在前 27 秒中获取的。 不会节省任何费用。 精度 = 5,字节数 = 5。 第五个字节将在中午 12 点后使用。 精度 = 6 和 7,字节 = 5。 未实现节省。 精度 = 8,字节数 = 6。 第六个字节将在凌晨 3 点后使用。 |
datetime2 |
是的 | 使用 6 到 9 个字节的整数数据表示形式。 前 4 个字节表示日期。 时间所占用的字节数将取决于指定时间的精度。 整数值表示自 1/1/0001 以来的天数,上限为 12/31/9999。 若要表示 2005 年中的日期,压缩需要 3 个字节。 因为它允许 2 到 4 字节的各种时间精度,所以没有时间上的节省。 因此,对于一秒精度,压缩使用 2 个字节的时间,这需要 255 秒后的第二个字节。 |
datetimeoffset |
是的 | 与datetime2 类似,只是格式上有 2 个字节表示的时区(HH:MM)。同样 datetime2 ,压缩可以保存 2 个字节。对于时区值,对于大多数情况,MM 值可能为 0。 因此,压缩可能会保存 1 个字节。 对于行压缩,存储中没有更改。 |
char |
是的 | 删除尾随填充字符。 请注意,无论使用哪种排序规则,数据库引擎都会插入相同的填充字符。 |
varchar |
否 | 无效。 |
text |
否 | 无效。 |
nchar |
是的 | 已删除尾随填充字符。 请注意,无论使用哪种排序规则,数据库引擎都会插入相同的填充字符。 |
nvarchar |
否 | 无效。 |
ntext |
否 | 无效。 |
binary |
是的 | 删除尾随零。 |
varbinary |
否 | 无效。 |
image |
否 | 无效。 |
cursor |
否 | 无效。 |
timestamp / rowversion |
是的 | 使用 8 个字节的整数数据表示形式。 每个数据库都有一个时间戳计数器,其值从 0 开始。 这可以像任何其他整数值一样进行压缩。 |
sql_variant |
否 | 无效。 |
uniqueidentifier |
否 | 无效。 |
table |
否 | 无效。 |
xml |
否 | 无效。 |
用户定义类型 | 否 | 这在内部表示为 varbinary 。 |
FILESTREAM | 否 | 这在内部表示为 varbinary 。 |