我有一个MySQL表,其中动态插入行。因为我无法确定字符串的长度并且不希望它们被切断,所以我将它们变成varchar(200),这通常比我需要的大得多。给varchar字段的长度是否超过必要的长度?
答案 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)那么你很可能会使用它在某些情况下,空间比所需空间多四倍。
这可能包括:
根据经验,无论如何,varchar都不需要比它需要更长的时间,性能问题或者不是,所以我建议你坚持这样做。通过询问/研究是一种理想的方法,需要花费更多精力来测量数据的大小,强制实施真正的限制或找出真正的限制。
如果你不能,如果你想对有疑问的情况做varchar(255)这样的事情,那么我建议你去做科学。这可能包括复制表,减少var char列的大小,然后从原始数据中复制数据并查看索引/行数据的大小(索引列也是,也可以将其作为主键使用可能在InnoDB中表现不同,因为行按主键排序)。至少这种方式你知道你是否对IO有影响,这往往是最敏感的瓶颈之一。对内存使用情况的测试更加困难,难以详尽地进行测试。我建议测试潜在的最坏情况(在内存结果中有大量中间的查询,请查看大型临时表的解释等)。
如果您知道表格中不会有很多行,您将不会使用该列进行连接,索引(尤其是复合,唯一)等,那么您很可能不会很多问题。