MySQL表中varchar长度的重要性

时间:2009-12-26 00:26:15

标签: sql mysql performance types

我有一个MySQL表,其中动态插入行。因为我无法确定字符串的长度并且不希望它们被切断,所以我将它们变成varchar(200),这通常比我需要的大得多。给varchar字段的长度是否超过必要的长度?

10 个答案:

答案 0 :(得分:271)

可能会对性能产生影响:在MySQL中,临时表和MEMORY表将VARCHAR列存储为固定长度列,填充到其最大长度。如果您设计的VARCHAR列比您需要的最大尺寸大,那么您将消耗更多内存。这会影响缓存效率,排序速度等。

答案 1 :(得分:58)

不,从某种意义上说,如果您在该列中存储的值总是(比方说)少于50个字符,则将列声明为varchar(50)varchar(200)具有相同的性能。< / p>

答案 2 :(得分:14)

VARCHAR非常适合您描述的情况,因为它代表“可变字符” - 根据您的示例,限制将是200个字符,但接受的任何内容都不会被接受将无法填充列的分配大小。

VARCHAR也占用更少的空间 - 值存储为一个字节或两个字节长度的前缀加数据。长度前缀表示值中的字节数。如果值不超过255个字节,则列使用一个长度字节;如果值可能需要超过255个字节,则列使用两个长度字节。

有关比较MySQL CHAR与VARCHAR数据类型的更多信息,请参阅this link

答案 3 :(得分:13)

尺寸是性能!尺寸越小越好。不是今天或明天,但有一天,无论你设计什么样的设计,当你遇到严重的瓶颈时,你的桌子都会变得很大。但是您可以预见到设计阶段可能首先出现的一些潜在瓶颈,并尝试扩展数据库快速,愉快地执行的时间,直到您需要重新考虑您的方案或通过添加更多服务器来横向扩展。

在您的情况下,您可能遇到许多性能泄漏:使用长varchar列几乎不可能进行大型连接。对这些列进行索引是一个真正的杀手。您的磁盘必须存储数据。一个内存页面可以容纳更少的行,而表扫描会慢得多。查询缓存也不太可能在这里帮助你。

你必须问自己:每年可能发生多少次插入?平均长度是多少?我是否真的需要超过200个字符,或者我可以在我的应用程序前端捕获它,即使通知用户最大长度?我可以将表格分成一个较窄的表格以进行快速索引和扫描,另一个表格可以保存额外的,不太常用的扩展大小数据吗?我可以将可能的varchar数据类型分类,然后将一些数据提取到一些较小的,可能是int或bool类型的列中,并以这种方式缩小varchar列吗?

你可以在这里做很多事。最好先进行第一次假设,然后使用实际测量的性能数据逐步重新设计。祝你好运。

答案 4 :(得分:5)

性能?没有。磁盘存储?是的,但它便宜又丰富。除非您的数据库增长到太字节,否则您可能还可以。

答案 5 :(得分:4)

有些人错误地认为varchar(200)在磁盘上占用的表大小超过varchar(20)。不是这种情况。只有当你超过255个字符时,mysql才会使用额外的字节来确定varchar字段数据的长度。

答案 6 :(得分:1)

可能会有性能点击 - 但通常不会达到大多数用户会注意到的水平。

当事先知道每个字段的大小时,MySQL确切地知道每个字段/行之间有多少字节,并且可以向前翻页而不读取所有数据。使用可变字符可以降低这种优化能力。

Does varchar result in performance hit due to data fragmentation?

更好,char vs varchar

对于大多数用途,你也可以 - 但 是一个区别,对于大型数据库,你有理由选择其中一个。

答案 7 :(得分:0)

作为varchar,而不仅仅是char,大小基于内部字段来指示其实际长度和字符串本身。所以使用varchar(200)与使用varchar(150)没有什么不同,除了你有可能存储 更多。

你应该考虑当一行增长时,更新会发生什么。但如果这种情况很少见,那么你应该没问题。

答案 8 :(得分:0)

根据数据类型名称表明这是VARCHAR即变量字符数据存储,mysql引擎本身根据存储的数据分配正在使用的内存,因此根据我的知识没有性能损失。

答案 9 :(得分:0)

在大多数情况下,您应该尝试查看与char列相同的varchar列,并保守地设置长度。你不必总是把var修饰符想象成影响你决定最大长度的东西。它应该被视为性能提示,而不是所提供的字符串具有不同的长度。

它不是一个必须严格遵循数据库内部的指令,它可以完全被忽略。请注意这一点,因为有时实施可能会泄漏(例如固定长度和填充),即使它不应该在理想的世界中。

如果您有一个varchar(255),那么您无法保证性能明智,它在所有情况下总是会对char(255)产生任何不同的行为。

使用手册中有关存储要求的建议,可以很容易地将其设置为255,65535等内容。这给人的印象是0(是的,它是一件事)和255之间的任何值都会产生同样的影响。然而,这不是可以完全保证的东西。

在行存储方面,存储要求确实倾向于成为正确且成熟的持久性存储引擎的良好指标。它并不是指数等事物的强大指标。

它有时候是一个很难的问题,究竟应该将一段字符串保持多长时间,将其设置为你知道应该在其中的最高限度,但这没有任何影响。不幸的是,这通常留给用户解决,而且它确实有点武断。你不能说永远不要超大字符串,因为有些情况你可能并不完全确定。

当字符串太长而不是截断时,您应确保MySQL查询抛出错误,以便至少您知道它是否可能因错误排放而过短。调整列的大小以放大或缩小它们可能是一项昂贵的DDL操作,应该牢记这一点。

在长度和性能发挥作用的地方也应考虑字符集。长度是指这个而不是字节。例如,如果使用utf8(不是MB4),则varchar(255)实际上是varbinary(3 * 255)。如果不运行测试并深入研究源代码/文档,很难知道这样的事情会如何发挥作用。因此,长度过大可能会产生意外膨胀的影响。这并不仅适用于性能。如果您有一天需要将varchar列的字符集更改为更大的字符集,那么如果您允许无条件地存在可以避免的长字符串,则可能最终达到某个限制而没有追索权。这通常是一个相当小的问题,但它确实出现了,最近一个重要的问题是引入了utf8mb4 for MySQL和索引,它们对密钥长度有限制。

如果结果是MAX(LENGTH(列))总是&lt; 64(例如,如果确定输入的限制与列定义不匹配)但是你有varchar(255)那么你很可能会使用它在某些情况下,空间比所需空间多四倍。

这可能包括:

  • 不同的引擎,有些可能会完全忽略它。
  • 缓冲区大小,例如更新或插入可能必须分配完整的255(虽然我没有检查源代码来证明这一点,但它只是一个假设)。
  • 索引,如果您尝试从许多varchar(255)列创建复合键,这将立即显而易见。
  • 中间表和可能的结果集。鉴于事务的工作方式,某些事情可能并不总是可以使用列中实际的字符串最大长度而不是定义的限制。
  • 内部预测优化可能会将最大长度作为输入。
  • 数据库实施版本的变化。

根据经验,无论如何,varchar都不需要比它需要更长的时间,性能问题或者不是,所以我建议你坚持这样做。通过询问/研究是一种理想的方法,需要花费更多精力来测量数据的大小,强制实施真正的限制或找出真正的限制。

如果你不能,如果你想对有疑问的情况做varchar(255)这样的事情,那么我建议你去做科学。这可能包括复制表,减少var char列的大小,然后从原始数据中复制数据并查看索引/行数据的大小(索引列也是,也可以将其作为主键使用可能在InnoDB中表现不同,因为行按主键排序)。至少这种方式你知道你是否对IO有影响,这往往是最敏感的瓶颈之一。对内存使用情况的测试更加困难,难以详尽地进行测试。我建议测试潜在的最坏情况(在内存结果中有大量中间的查询,请查看大型临时表的解释等)。

如果您知道表格中不会有很多行,您将不会使用该列进行连接,索引(尤其是复合,唯一)等,那么您很可能不会很多问题。