关于sql:MySQL表中varchar长度的重要性

Importance of varchar length in MySQL table

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


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


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


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

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

有关比较MySQL CHAR与VARCHAR数据类型的更多信息,请参阅此链接。


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

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

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

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


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


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


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

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

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

更好的是,char vs varchar。

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


在大多数情况下,您应该尝试查看与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(列))总是<64(例如,如果确定输入的限制与列定义不匹配)但是你有varchar(255)那么就有了在某些情况下,您将使用比所需空间多四倍的空间。

这可能包括:

  • 不同的引擎,有些可能会完全忽略它。
  • 缓冲区大小,例如更新或插入可能必须分配完整的255(虽然我没有检查源代码来证明这一点,但它只是一个假设)。
  • 索引,如果您尝试从许多varchar(255)列创建复合键,这将立即显而易见。
  • 中间表和可能的结果集。鉴于事务的工作方式,某些事情可能并不总是可以使用列中实际的字符串最大长度而不是定义的限制。
  • 内部预测优化可能将最大长度作为输入。
  • 数据库实现版本的变化。
  • 根据经验,无论如何,varchar都不需要比它需要更长的时间,性能问题或者没有,所以我建议你尽可能坚持。通过询问/研究是一种理想的方法,需要花费更多精力来测量数据的大小,强制实施真正的限制或找出真正的限制。

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

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

    好。


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


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

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