具有小数据的 varchar(max) 列的开销
Posted
技术标签:
【中文标题】具有小数据的 varchar(max) 列的开销【英文标题】:overhead of varchar(max) columns with small data 【发布时间】:2009-05-13 14:21:48 【问题描述】:作为来自外部源的大量数据加载的一部分,暂存表是使用 varchar(max) 列定义的。其想法是,每列都将能够保存它在源 CSV 文件中找到的任何内容,并且我们稍后将验证数据(针对类型、大小、精度等)。
但我担心 varchar(max) 列对于少于 200 个字符的列有很多开销。设计这个的人向我保证这是 ETL 的最佳实践,但我想我会在社区中验证这个断言。
【问题讨论】:
【参考方案1】:如果空间允许,VARCHAR(MAX) 列值将存储在表行中。因此,如果您有一个 VARCHAR(MAX) 字段并且它是 200、300 字节,那么它很可能会与您的其余数据内联存储。这里没有问题或额外的开销。
只有当单个 SQL Server 页面 (8K) 无法容纳单行的全部数据时,SQL Server 才会将 VARCHAR(MAX) 数据移动到溢出页面中。
总而言之,我认为您可以两全其美 - 尽可能内联存储,必要时溢出存储。
马克
PS:正如 Mitch 指出的那样,可以关闭此默认行为 - 但是我没有看到任何令人信服的理由这样做......
【讨论】:
我有一个始终为空的 varchar(max) 列。它只是出于遗留原因(并使我在 ASP.net 中的旧代码无需更改即可工作)。因此,如果我猜对了,如果我删除它,我的数据库不会变得更小(如果更小的话)。对吗? 根据 Jeff Hall 的回答,这取决于行数。假设 1 Mio。行我会节省 2 MB。对吗?【参考方案2】:varchar(n) 和 varchar(max) 的存储开销相同 存储大小为实际输入数据长度+2字节
MSDN Reference
查看这些类似的 SO 问题:
https://***.com/questions/166371/varcharmax-versus-varcharn-in-ms-sql-server Are there any disadvantages to always using nvarchar(MAX)?
【讨论】:
【参考方案3】:据我所知,您可能正在考虑的开销(以与在 sql server 中存储 TEXT 或 BINARY 值相同的方式将数据存储在行外)仅适用于数据大小超过 8000 字节的情况.因此,在 ETL 过程中使用较小的列应该没有问题。
【讨论】:
取决于表选项“large values types out of row”的设置,如果设置为“ON”,它将使用16字节的指针来存储表外的数据。 米奇:是什么让你打开这个选项?在我看来,你会失去 MAX 类型的所有好处,不是吗?【参考方案4】:如果您在 MSSQL2005 中使用 varchar(max) 或 varbinary(max),SSIS 会为记录中的每一列创建一个临时文件,这会降低您的性能并成为一个大问题。 MS声称他们在MSSQL2008中解决了这个问题。
【讨论】:
这听起来很奇怪——你必须用一些参考资料来支持它——例如指向微软“声明”的链接 我亲眼所见。我们有一个具有 16 个内核和 64 GB RAM 的 SSIS 服务器,当我们使用 varchar(max)/varbinary(max) 创建超过 800 万条记录时,将需要 12 多个小时才能创建它们。但是如果我们使用 varchar(8000)/varchar(8000) 那么它会在几分钟内准备好。我会尝试找到索赔,我在网上的某个地方看到过。 这不是确切的事情,但 MS 说他们改进了创建临时文件的分配。 connect.microsoft.com/SQLServer/feedback/…【参考方案5】:好吧,我想说不应该有那么大的开销,因为我认为 sql 不会自动为 nvarchar 分配分配的数据量,而是只分配插入所需的数据,但我没有任何东西可以证明或支持这个想法。
【讨论】:
以上是关于具有小数据的 varchar(max) 列的开销的主要内容,如果未能解决你的问题,请参考以下文章
RODBC sqlQuery() 在应该返回 varchar(MAX) 时返回 varchar(255)
Cassandra/Datastax:如何在 java 中获取具有列表数据类型的列的值