varchar是否会因数据碎片而导致性能下降?

时间:2009-10-27 14:23:52

标签: sql database-design database

varchar列如何由数据库引擎在内部处理?对于定义为char(100)的列,DBMS在磁盘上分配100个连续字节。但是对于定义为varchar(100)的列,可能并非如此,因为varchar的整个点不会分配比存储列中存储的实际数据值所需的更多空间。因此,当用户将包含空varchar(100)列的数据库行更新为包含80个字符的值时,该80个字符的空间从哪里分配?似乎varchar列必须导致实际数据库行的大量碎片,至少在最初将列值插入为空或NULL时,然后使用实际值进行更新的情况下。这种碎片是否导致数据库查询性能下降,而不是使用char类型值,其中存储在行中的列的空间是连续分配的?显然使用varchar会导致比使用char更少的磁盘空间,但是在优化查询性能时会出现性能损失,特别是对于在初始插入后经常更新其值的列?

6 个答案:

答案 0 :(得分:7)

你在问题​​中做了很多假设,但这些假设并不一定正确。

任何DBMS中a列的类型都不会告诉您关于该数据存储性质的任何信息,除非文档清楚地告诉您数据是如何存储的。如果没有说明,您不知道它是如何存储的,DBMS可以自由地将存储机制从发布更改为发布。

实际上,有些数据库在内部将CHAR字段存储为VARCHAR,而其他数据库则根据声明的列大小决定如何存储列。某些数据库将VARCHAR与其他列存储在一起,一些存储BLOB数据,另一些存储实现其他存储,某些数据库在更新列时始终会重写整行,而其他数据库则不会。一些pad VARCHAR允许在不重新定位存储的情况下进行有限的将来更新。

DBMS负责确定如何存储数据并以快速一致的方式将其返回给您。通常在检测到任何性能问题之前,我总是惊讶于有多少人试用数据库。

答案 1 :(得分:4)

在数据库引擎中使用的数据结构远比你给它的信誉复杂得多!是的,存在碎片问题以及更新具有大值的varchar可能导致性能损失的问题,但是如果没有更全面地了解所涉及的数据结构,则很难解释/理解这些问题的含义。

对于MS Sql server,您可能需要从理解页面开始 - 基本的存储单元(参见http://msdn.microsoft.com/en-us/library/ms190969.aspx

就修复与可变存储类型对性能的性能影响而言,需要考虑以下几点:

  • 使用可变长度列可以提高性能,因为它允许更多行适合单个页面,这意味着更少的读取
  • 使用可变长度列需要特殊的偏移值,并且维护这些值需要轻微的开销,但这种额外的开销通常是可以忽略不计的。
  • 另一个潜在成本是当包含该行的页面几乎已满时增加列大小的成本

正如您所看到的,情况相当复杂 - 一般来说,您可以相信数据库引擎在处理可变数据类型时非常擅长,并且当可能存在显着差异时,它们应该是所选择的数据类型。列中保存的数据长度。

此时我还将推荐一本优秀的书籍“Microsoft Sql Server 2008 Internals”,以便更深入地了解这样复杂的事情!

答案 2 :(得分:3)

答案取决于具体的DBMS。对于Oracle来说,最终可能会以“链式行”的形式出现碎片,并且会导致性能下降。但是,您可以通过在表块中预先分配一些空白空间来缓解这种情况,以允许由于更新而进行一些扩展。但是,CHAR列通常会使表格更大,这会对性能产生影响。 CHAR还有其他问题,例如空白填充比较,这意味着,在Oracle中,使用CHAR数据类型几乎从不是一个好主意。

答案 3 :(得分:2)

您的问题太笼统,因为不同的数据库引擎会有不同的行为。如果你真的需要知道这一点,我建议你设置一个基准来编写大量的记录并计算它。您需要足够的记录才能写入至少一个小时。

如你所知,如果你用空字符串(“”)编写插入所有记录然后将它们更新为100个合理随机的字符,而不仅仅是100 Xs,那将会很有趣。

如果您尝试使用SQLITE并且没有看到任何显着差异,那么我认为大型数据库服务器不可能进行所有分析和调优,而不是SQLITE。

答案 4 :(得分:2)

这将完全针对数据库。

我知道在Oracle中,数据库将保留每个块的一定百分比以供将来更新(PCTFREE参数)。例如,如果PCTFREE设置为25%,则块将仅用于新数据,直到75%已满。通过这样做,空间留给行增长。如果行增长使得25%的保留空间完全用完,那么最终会出现链接行和性能损失。如果发现表具有大量链接行,则可以调整该表的PCTFREE。如果你有一张永远不会有任何更新的表格,那么PCT的PCT值为零有意义

答案 5 :(得分:1)

在SQL Server中,varchar(varchar(MAX)除外)通常与行的数据的其余部分一起存储(如果行的数据为&lt; 8KB,则在同一页面上,如果<64KB,则在相同的范围内)。仅存储TEXT,NTEXT,IMAGE,VARHCAR(MAX),NVARHCAR(MAX),XML和VARBINARY(MAX)等大数据类型。