【问题标题】:SQL Server Maximum Row size Vs Varchar(Max) sizeSQL Server 最大行大小与 Varchar(Max) 大小
【发布时间】:2016-04-23 00:23:00
【问题描述】:

我正在尝试估计 SQL Server 2008 R2 的数据库大小。我有一个表,其中包含一个 INTEGER 主键和 39 个 VARCHAR(MAX) 类型的文本列。

我已经搜索并找到了两个语句。

  • 一个表每行最多可以包含 8,060 个字节。
  • Varchar(max) 的最大存储容量为 2 GB。

我很困惑估计大小。如果行有限制,如何在每列中存储 2 GB?

我不是数据库专家,可能我没有正确理解它。

谁能解释一下如何估算?

谢谢

【问题讨论】:

  • 你看过这个链接stackoverflow.com/questions/7892334/…我希望对你有帮助。
  • 您想获得当前的大小,还是想知道在添加一定数量的行后它可以有多大?
  • VARCHAR(MAX)VARBINARY(MAX) 这样的“大”数据类型的处理方式与其他数据类型不同。由于它们最多可以拥有 2 GB 的数据,因此它们最终可能会跨越大量“溢出”页面。在这种情况下,它们将在“基本”数据页面上占用一定数量的存储空间(它记录在某处 - 现在不知道),而 intdatetime 等的其他列占用基本页面上的固定存储量
  • @srutzky 我想知道它有多大。
  • 取决于列要存储的内容。一行可以存储 140 字节,而另一行可以存储 78 GB,具体取决于数据。

标签: sql-server sql-server-2008


【解决方案1】:

在 Microsoft SQL Server 中,数据(包括索引)存储在一个或多个 8k(8192 字节)“页面”中。有不同类型的页面可用于处理各种情况(例如 Data、LOB、Index、AllocationMap 等)。每个页面都有一个标题,它是关于该页面及其包含内容的元数据。

大多数数据都存储在行本身中,而这些行中的一个或多个又存储在“行内数据”的页面中。由于行标题占用的空间,最大的一行(对于“行内”数据)是 8060 字节。

但是,并非所有数据都存储在行中。对于某些数据类型,数据实际上可以存储在“LOB 数据”页面上,而指针留在“行内”数据中:

  • 任何人都不应再使用的旧版/已弃用 LOB 类型(TEXTNTEXTIMAGE)默认情况下始终将其数据存储在 LOB 页面上并始终使用 16 字节指针到那个 LOB 页面。

  • 默认情况下,较新的 LOB 类型(VARCHAR(MAX)NVARCHAR(MAX)VARBINARY(MAX)XML)将尝试将数据直接放入行中(如果它适合的话)。否则它将数据存储在 LOB 页面上并使用 24 - 72 字节的指针(取决于 LOB 数据的大小)。

这就是您如何在单行中存储多达 78 GB + 4 字节(不能忘记 INT 主键 ;-):最大行大小将在 940 字节之间((39 * 24 ) + 4) 和 2812 字节 ((39 * 72) + 4)。但同样,这只是最大范围;如果 39 个VARCHAR(MAX) 字段中的每个字段中的数据只有 10 个字节,那么所有数据都将存储在行内,并且行大小将为 394 个字节 ((39 * 10) + 4)。

鉴于您有这么多可变长度字段(无论它们是否为 MAX),估计未来行大小的唯一方法是了解您将在此表中存储哪些数据。虽然,一个包含全部甚至大部分 MAX 数据类型的表意味着没有人真正知道该表中将存储什么。

按照这些思路,应该指出这是一个可怕的建模表/对 MAX 数据类型字段的可怕使用,应该重构。

有关数据页面结构的更多详细信息,请参阅我对以下 DBA.StackExchange 问题的回答:

SUM of DATALENGTHs not matching table size from sys.allocation_units

【讨论】:

  • Soloman,您是否有描述您所说的 24-72 字节开销的链接?我问是因为我做了一些测试,发现这是非常正确的,而且不仅仅是存储的 16 字节指针。
  • 嗨@JeffModen。对,16 字节指针主要用于已弃用的 LOB 类型(IMAGETEXTNTEXT),但如果使用 sp_tableoption 设置 text in row 则并非总是如此(甚至不确定有多少人知道该选项)。或者,另一个不常见的情况是使用sp_tableoptionMAX 类型设置large values out of row,这导致它们始终使用16 字节指针。但请查看我的答案末尾的链接,因为它指向我的更详细的答案,我刚刚更新了有关此问题的更多详细信息,以及外部参考和测试脚本。
  • 谢谢所罗门。我在 improve.dk/… 上找到了 Mark S. Rasmussen 的链接
  • @JeffModen 那么,您没有查看我在此答案底部链接的其他答案吗? ;-) 不仅在其他答案中使用了相同的链接,而且我还添加了一些在 Mark 的博客文章中没有提到的细节(以及一个指向测试脚本的链接,可以引导您完成大部分内容)。此外,我发现 Inline-Root 的上限为 42,000,而 Mark 的帖子指出限制仅为 40,000。这里的答案只是基于其他答案的部分内容的总结。请查看其他答案(“SUM of DATALENGTHs ...”链接)。
  • 不...我确定没有。您所指的链接标题中没有任何内容表明我正在寻找任何东西,并且链接上方的描述说这是有关数据页面结构的更多信息,我在页面级别已经知道.我只需要快速回答 24-72 的问题。由于您知道 24-72 号码的来源,如果您在此线程上发布直接链接会很好。现在看看那篇文章,好文章,所罗门。
【解决方案2】:

当您使用 Varchar(MAX) 时,数据可以存储在行内(称为页)(如果内容小于 8000 字节)。如果内容大于 8000 字节,则数据存储为 LOB(“页外”),并且仅对实际位置的引用存储在页内。老实说,考虑到 Varchar(MAX) 列中的数据可能是任意长度,我真的不知道有什么体面的方法来估计整个数据库的大小。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多