【问题标题】:Does the size used with NVARCHAR matter?与 NVARCHAR 一起使用的大小是否重要?
【发布时间】:2012-04-02 21:03:58
【问题描述】:

每次创建表时,我都想知道如果我说nvarchar (100)nvarchar (1000) 是否存在任何性能差异,假设实际字符串大小将小于100。有吗?

【问题讨论】:

标签: sql-server-2008


【解决方案1】:

根据the documentation

nvarchar [ ( n | max ) ]

可变长度的 Unicode 字符串数据。 n 定义字符串长度,可以是 1 到 4,000 之间的值。 max 表示最大存储大小为 2^31-1 字节(2 GB)。 存储大小(以字节为单位)是实际输入数据长度的两倍 + 2 个字节。

因此,在计算存储大小时,只有输入数据的实际长度很重要。

文档没有说明它为什么存在,但长度参数很有用,因为它强制执行简单的限制约束(例如,有人不能输入 2 GB 的文本作为他们的“名称”)。

【讨论】:

  • 确实,如果有一个单独的原因应该限制某些东西,那么这是添加约束的一个很好的理由。也许有一条业务规则说“数据元素 X 可能永远不会超过 Y 个字符”。或者,系统的另一部分可能存在约束,为了在整个系统中保持数据完整性,应该在整个系统中保持约束。
  • 正确。请注意,nvarchar(max) 的存储方式不同,但不应简单地用作 nvarchar(x) 的替代品。存储空间是一样的,但是存储起来更像是一个BLOB而不是一个内联字段。
  • 我刚刚通过调整 rusanu.com/2010/03/22/… 的测试以使用 nvarchar 而不是 varchar 来验证 @AndrewBarber 的评论。
  • @HLGEM 的回答提醒我,有一个临界点 - 在大小为 4000 之后 - nvarchar 的行为会发生变化。文档没有明确说明如果您声明大小为 4001 或更大会发生什么。
  • 链接文档页面上的措辞已更改(页面编辑日期为 2018-10-22)为“存储大小为 n 字节 + 2 字节的两倍”,这与此答案相矛盾。我希望这是一个错误或误导性文件的案例,有人可以确认吗?
【解决方案2】:

当您需要 nvarchar(10) 时不应使用 nvarchar(1000) 的原因是为了帮助防止错误数据输入到您的数据库中。除非你喜欢电话号码说“如果你想要一个真正的答案,就打电话给胖秘书而不是可爱的秘书。”(不是我曾经在发送给我们的实际客户文件中找到的随机示例)用户会很快弄清楚哪些字段足够大,可以使用它们来存储笔记,这些字段往往会使字段中的数据随着时间的推移变得无用。

对于 nvarchar(Max),除非您希望有超过 4000 个字符,否则使用它是一个坏主意。查看 indexing 和 varchar(max) 以了解原因。

【讨论】:

  • 另一方面,在大多数情况下,我认为这只是“最后的健全性检查”。也就是说,对于电话号码,我可能会使用varchar(20)(我喜欢四舍五入到 10、20、100、200)来说明不同的地区/国家代码、分机号等。通常应该有额外的数据验证约束(DB、DAL 或其他部分)以确保数据符合任何现有的业务规则。
【解决方案3】:

是的,从性能的角度来看,这很重要。

查询优化器查看此元数据来规划查询。它根据提供的长度估计行大小,这可能会导致性能问题。例如,当您需要对 varchar(10) 列进行排序时,它可能计划在 RAM 上运行排序操作,但可能计划在辅助存储上运行对 varchar(1000) 的相同查询。

我尝试使用领域知识并估计所需的大小。此外,您可能需要为将来的维护留出一些空间。例如,如果您认为您的数据最多可以包含 50 个字符,请使用 varchar(70) 而不是 50,以便它可以处理应用程序使用中不可预知的未来变化。

我是从这篇博文中了解到的(我不是作者):http://aboutsqlserver.com/2010/08/18/what-is-the-optimal-size-for-variable-width-columns/


注意:不要盲目选择较小的长度。更改字段大小可能会成为一个很大的维护难题。我记得我为 LastName 字段选择了一个较小的长度,并且一些用户因此无法在系统中注册。我们必须更新正在使用的关键数据库(增加字段长度需要时间),并编译程序并重新部署。如果我选择了合适的字段大小,我可以避免所有这些麻烦。

您可能还想了解 nvarchar(max) 和 nvarchar(n) 之间的差异,因为 n>4000 表示 4000 使得该字段与 nvarchar(max) 基本相似。 (Are there any disadvantages to always using nvarchar(MAX)?)

【讨论】:

    【解决方案4】:

    关于大小与性能,请记住,SQL Server 将存储nvarchar/varchar 的数据初始值和nchar/char 的整个值以空间形式。例如:nvarchar(1000) 与存储的数据 test data 最初将占用 9*2 字节的空间或 18 字节。而 nchar(1000) 无论如何都会占用 1000*2 字节(2000 字节)。

    然后它继续在页面上添加下一组数据(即 8k),直到页面满足(或接近)为表格设置的填充因子。然后开始一个新的页面。现在假设用户需要更新该数据并在前一个字段中输入一些内容,比如说 800 个字符长。现在该值需要更新并将显着增长,但现在页面已满,当该字段的数据必须增长时,页面需要拆分并为数据让路(除非填充因子足够低以允许增长)。

    该页面拆分将聚合为索引碎片,并导致较慢的搜索/查找时间和较长的更新时间。因此,如果数据发生显着变化,对性能的影响可能会有所不同。

    通常情况下,答案是:“取决于”。

    【讨论】:

    • 所以你是说 nvarchar(1000) 将保留 1000*2 字节的空间,即使内容只占用 40 字节?因为我认为它不会。
    【解决方案5】:

    至少在 sql server 数据库中,不允许对类型为 nvarchar(max) 的列创建唯一约束。应限制为 nvarchar(450) 才能成功添加此约束。

    【讨论】:

    • 当列的总大小超过 900 字节时,不允许创建主键,如果您使用最大大小为 450 的两个 nvarchar 列作为复合主键,则很容易出现这种情况。
    【解决方案6】:

    由于 nvarchar 是一种可变长度的数据类型,它只会存储您分配给它的数据(每个字符 2 个字节)加上 2 个字节的长度信息,主要用于中文等双字节语言。

    就我个人而言,当我知道某个限制(即 URL 查询字符串限制、文件路径 szie 限制或我自己的限制)时,我会使用 varchar(n)。当最大长度未定义并且可能超过 8000 个字符时,我使用 varchar(max)。而且我几乎从不使用 nvarchar,主要是因为我们的应用程序永远不会国际化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多