Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql varchar是否会因数据碎片而导致性能下降?_Sql_Database Design_Database - Fatal编程技术网

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

Sql varchar是否会因数据碎片而导致性能下降?,sql,database-design,database,Sql,Database Design,Database,数据库引擎如何在内部处理varchar列 对于定义为char(100)的列,DBMS在磁盘上分配100个连续字节。但是,对于定义为varchar(100)的列,情况可能并非如此,因为varchar的要点是分配的空间不超过存储在列中的实际数据值所需的空间。例如,当用户将包含空varchar(100)列的数据库行更新为包含80个字符的值时,这80个字符的空间从何处分配 似乎varchar列必须导致实际数据库行的大量碎片,至少在列值最初插入为空或NULL,然后用实际值更新的情况下是如此。与连续分配存储

数据库引擎如何在内部处理varchar列

对于定义为
char(100)
的列,DBMS在磁盘上分配100个连续字节。但是,对于定义为
varchar(100)
的列,情况可能并非如此,因为
varchar
的要点是分配的空间不超过存储在列中的实际数据值所需的空间。例如,当用户将包含空
varchar(100)
列的数据库行更新为包含80个字符的值时,这80个字符的空间从何处分配


似乎
varchar
列必须导致实际数据库行的大量碎片,至少在列值最初插入为空或NULL,然后用实际值更新的情况下是如此。与连续分配存储在行中的列的空间的char类型值相反,这种碎片是否会导致数据库查询的性能下降?显然,使用
varchar
会比使用char减少磁盘空间,但是在优化查询性能时,特别是对于在初始插入后值经常更新的列,性能是否会受到影响?

您在问题中做出了许多不一定正确的假设

任何DBMS中的列类型都不会告诉您该数据存储的性质,除非文档清楚地告诉您数据是如何存储的。如果没有说明,您就不知道它是如何存储的,DBMS可以自由地在不同版本之间更改存储机制

事实上,一些数据库在内部将CHAR字段存储为VARCHAR,而其他数据库则根据声明的列大小决定如何存储列。有些数据库使用其他列存储VARCHAR,有些数据库使用BLOB数据,有些数据库实现其他存储,有些数据库总是在更新列时重写整行,有些数据库则不这样做。有些安装了VARCHAR,以允许将来进行有限的更新,而无需重新定位存储


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

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

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

正如您所建议的,如果您使用空字符串(“”)写入插入所有记录,然后将它们更新为100个合理随机的字符,而不仅仅是100个X,那么将会发生什么,这将非常有趣


如果您在SQLITE中尝试这一点,并且没有看到显著的差异,那么我认为,经过所有分析和调优,较大的数据库服务器不太可能比SQLITE更差。

在SQL Server中,varchar(除了varchar(MAX))通常与行的其余数据一起存储(如果行的数据小于8KB,则在同一页上;如果行的数据小于64KB,则在同一范围上。仅大数据类型,如TEXT、NTEXT、IMAGE、VARHCAR(MAX)、NVARHCAR(MAX)、XML和VARBINARY(MAX)单独存储。

数据库引擎中使用的数据结构比您认为的要复杂得多!是的,存在碎片问题和更新具有较大值的varchar可能导致性能下降的问题,但是很难解释/理解这些问题的含义我们还不能更全面地理解所涉及的数据结构

对于MS Sql server,您可能希望从了解页面开始—存储的基本单元(请参阅)

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

  • 使用可变长度列可以提高性能,因为它允许在单个页面上容纳更多的行,这意味着更少的读取
  • 使用可变长度列需要特殊的偏移量值,维护这些值需要少量的开销,但是这种额外开销通常是可以忽略的
  • 另一个潜在成本是当包含该行的页面几乎已满时,增加列大小的成本
正如您所看到的,情况相当复杂-一般来说,您可以相信数据库引擎非常擅长处理可变数据类型,并且当列中保存的数据长度可能存在显著差异时,它们应该是首选的数据类型


在这一点上,我还将推荐一本优秀的书“Microsoft Sql Server 2008内部构件”,以便更深入地了解像这样的事情到底有多复杂!

这将是完全特定于数据库的

我确实知道,在Oracle中,数据库将为将来的更新保留每个数据块的一定百分比(PCTFREE参数)。例如,如果PCTFREE设置为25%,则一个数据块将仅用于新数据,直到其已满75%。这样做,空间就剩下了