1

我正在调整一个审计方案:https://weblogs.asp.net/jongalloway/adding-simple-trigger-based-auditing-to-your-sql-server-database要求创建这样的审计表:

CREATE TABLE Audit
(
AuditID [int]IDENTITY(1,1) NOT NULL,
Type char(1), 
TableName varchar(128), 
PrimaryKeyField varchar(1000), 
PrimaryKeyValue varchar(1000), 
FieldName varchar(128), 
OldValue varchar(1000), 
NewValue varchar(1000), 
UpdateDate datetime DEFAULT (GetDate()), 
UserNamevarchar(128)
)

我想确保为插入到Audit表中的每一行存储尽可能少的内容。就我而言,我可以缩短 , , 的宽度,因为我TableName知道这些东西的实际最大长度。我有一个特定的表,它有一个定义为 nvarchar(2000) 的特定列,所以如果我继续使用这种通用方法,我将需要使用 nvarchar(2000)和.PrimaryKeyFieldPrimaryKeyValueFieldNameOldValueNewValue

我想知道 SQL Server 关于页面中实际使用的存储空间的内部优化。当使用 long varchars 或 nvarchars 存储行时,是实际用于将行存储在页面中的完整定义长度,还是 SQL Server 仅存储实际使用的字节。例如,如果只Hello!存储在上面,那么这样一行在页面中实际占用OldValue多少字节?OldValue

4

2 回答 2

0

当使用 long varchars 或 nvarchars 存储行时,是实际用于将行存储在页面中的完整定义长度,还是 SQL Server 仅存储实际使用的字节

即使您定义了一个可变长度的列,SQL 也只会将存储空间用于声明的值。

此处已对此进行了介绍:如何将 varchar 值存储在 SQL Server 数据库中?

以下是马丁史密斯回答的相关部分

所有 varchar 数据都存储在行尾的可变长度部分(如果行不下,则存储在 offrow 页面中)。它在该部分中消耗的空间量(以及它是否最终脱离行)完全取决于实际数据的长度而不是列声明

下面是一个示例演示,以证明相同

create table dbo.test1

(
fixedlencol varchar(400),
varlengthcol varchar(max),
var_len_Nvarcahrcol nvarchar(max)
)

insert into dbo.test1
values
('a','abc','def')

现在,如果按照此处的示例使用 DBCC PAGE 和 DBCC IND:存储引擎内部:使用 DBCC PAGE 和 DBCC IND 确定页面拆分是否回滚

下面是输出,我得到了第一行插入

插槽 0 列 1 偏移 0xf长度 1长度(物理) 1

固定lencol = a

varlengthcol = [BLOB 内联数据] 插槽 0 列 2 偏移量 0x10长度 3长度(物理)3

varlengthcol = 0x616263

var_len_Nvarcahrcol = [BLOB 内联数据] 插槽 0 列 3 偏移量 0x13长度 6长度(物理)6

最后一列占用比实际长度双字节的原因是由于 Nvarchar..

于 2017-04-09T14:01:56.443 回答
0

因为nvarchar(N)它将是2 + (2*N)该值在行中存储的最大字节数。前 2 个是长度,然后是实际存储在行中的每个 unicode 字符 2 个字节。这是占用的最大空间。

如果您的 unicode 字符串只有 15 个字符,那么它将是 32 个字节(即使作为nvarchar(2000)数据类型)。

我还建议sysname在脚本中使用 for 系统对象的名称以实现向前(和向后)兼容性。

您可能还对此审计脚本感兴趣:快速简便的审计表 - Dave Britten

于 2017-04-09T13:40:32.537 回答