减小 NVARCHAR 列的大小有好处吗

问题描述 投票:0回答:3

我有一个存储数百万行的 SQL Server 2008 数据库。有几个 NVARCHAR 列将永远不会超过列的当前最大长度,也不会由于应用程序限制而接近它。

即 地址 NVARCHAR 字段的长度为 50 个字符,但绝不会超过 32 个字符。

将 NVARCHAR 列的大小减少到其实际最大长度(即在地址字段的情况下,为 32 个字符)对我来说是否有性能优势或节省空间优势。或者因为它是一个可变长度字段,所以不会有什么区别吗?

sql-server sql-server-2008 nvarchar
3个回答
2
投票

设置NVARCHAR的字符数主要是为了验证目的。如果出于某种原因您不希望数据超过 50 个字符,那么数据库将通过不允许额外数据来强制您执行该规则。

如果总行大小超过阈值,则可能会影响性能,因此通过限制长度,您可以通过不允许行大小超过该阈值而受益。但就你而言,这似乎并不重要。 原因是 SQL Server 可以在一个页面上容纳更多的行,从而减少磁盘 I/O,并且可以在内存中存储更多的行。

此外,SQL Server 中的最大行大小为 8KB,因为这是页面的大小,并且行不能跨越页面边界。如果插入的行超过 8KB,多余的数据将存储在行溢出页中,这可能会对性能产生负面影响。


2
投票

n/var/char
列定义减少到最大长度不会带来预期的性能或节省空间的好处。然而,可能还有其他好处。

  • 该列不会意外插入更长的值而不产生错误(对于设计良好的系统的“快速失败”特性来说是理想的)。

  • 该列向下一个检查表的开发人员传达有关数据的信息,这有助于理解。开发人员不会对数据的用途感到困惑,并且不得不浪费时间来确定代码的字段验证规则是否错误或列定义是否错误(因为它们在逻辑上应该匹配)。

  • 如果您的专栏确实需要延长长度,您可以提前确定潜在后果。精通数据库的专业人员可以利用这个机会来查看即将需要新列长度的值是否会对现有行或查询性能产生负面影响,因为每行的数据量会影响读取次数需要满足查询。


0
投票

在 sqlservercentral.com 上的 [N]Varchar(4000) 和 Performance 中,Eddie Wuerch 评论道:

当估计行的宽度以请求内存时,varchar 和 nvarchar 列假定为半满。 varchar(2000) 列将导致每行 1000 字节的内存请求,并且 nvarchar(2000) 将导致 2000 字节请求(2000 的 1/2 = 1000 字符 * 每个字符 2 个字节)。

还有

任意值的最大长度小于60字节, 95% 的值不超过 37 字节。使用正确的数据类型,这 查询需要不到 256KB 才能完全运行,包括排序 操作员。通过放大可变字符的可能大小 类型,会分配并浪费大量额外内存。全部 测试的查询返回完全相同的数据。

他创建了这个样本

CREATE TABLE dbo.ColumnSizes(
    id    int    NOT NULL,
    NVarChar64 nvarchar(64) NOT NULL, 
    NVarChar256 nvarchar(256) NOT NULL, 
    NVarChar1024 nvarchar(1024) NOT NULL, 
    NVarChar4000 nvarchar(4000) NOT NULL,
    NVarCharMax nvarchar(max) NOT NULL,
    VarChar64  nvarchar(64) NOT NULL,
    VarChar256 nvarchar(256) NOT NULL,
    VarChar1024 nvarchar(1024) NOT NULL,
    VarChar8000 varchar(8000) NOT NULL,
    VarCharMax varchar(max) NOT NULL,
    CONSTRAINT pkColSz PRIMARY KEY CLUSTERED (id) 
)
GO
INSERT dbo.ColumnSizes 
(
        id, NVarChar64, NVarChar256, NVarChar1024, 
        NVarChar4000, NVarCharMax,  VarChar64, VarChar256, 
        VarChar1024, VarChar8000, VarCharMax
)
SELECT object_id, name, name, name, name, name, 
       name, name, name, name, name 
FROM sys.all_objects;

他总结出使用 XE 会话来获取内存使用情况

任意值的最大长度小于60字节, 95% 的值不超过 37 字节。使用正确的数据类型,这 查询需要不到 256KB 才能完全运行,包括排序 操作员。通过放大可变字符的可能大小 类型,会分配并浪费大量额外内存。全部 测试的查询返回完全相同的数据。 [已用百分比] 列显示 将样本数据存储在 NVarchar(4000) 中会导致 99% 授予的内存被浪费了。

 TestColumn     EstRowWidth IdealMemKB  GrantedMemKB UsedMemKB   Used % Granted %
 -------------- ----------- ----------- ------------ ----------- ------ ---------
 id             11          NULL        NULL         NULL        NULL   NULL
 NVarChar64     75          NULL        NULL         NULL        NULL   NULL
 VarChar64      75          NULL        NULL         NULL        NULL   NULL
 NVarChar256    267         NULL        NULL         NULL        NULL   NULL
 VarChar256     267         NULL        NULL         NULL        NULL   NULL
 NVarChar1024   1035        5344        5344         216         4      100
 VarChar1024    1035        5344        5344         216         4      100
 NVarChar4000   4011        11872       11872        216         1      100
 VarChar8000    4011        11872       11872        168         1      100
 NVarCharMax    4035        11936       11936        272         2      100
 VarCharMax     4035        11936       11936        224         1      100
© www.soinside.com 2019 - 2024. All rights reserved.