Answers:
不,在某种意义上说,如果您存储在该列中的值始终(例如)少于50个字符,则将该列声明为varchar(50)
或varchar(200)
具有相同的性能。
这可能会对性能产生影响:在MySQL中,临时表和MEMORY
表将VARCHAR
列存储为固定长度的列,并填充为其最大长度。如果您设计的VARCHAR
列比所需的最大尺寸大得多,则会消耗更多的内存。这会影响缓存效率,排序速度等。
MEMORY
认为该表太大时,会将其写入磁盘,从而导致性能显着下降。
尺寸就是性能!尺寸越小越好。并非今天或明天,但总有一天,无论您采用何种设计,遇到严重瓶颈时,您的桌子都会变大。但是,您可以预见在设计阶段可能首先出现的一些潜在瓶颈,并尝试延长数据库将快速而愉快地执行的时间,直到您需要重新考虑方案或通过添加更多服务器来水平扩展时为止。
在您的情况下,您可能会遇到许多性能泄漏:长varchar
列几乎不可能实现大联接。在这些列上建立索引是真正的杀手er。您的磁盘必须存储数据。一个内存页可以容纳更少的行,并且表扫描的速度将慢得多。而且查询缓存将不太可能在这里为您提供帮助。
您必须问自己:每年可能发生多少次插入?平均长度是多少?我是否真的需要200个以上的字符,还是可以通过告知用户最大长度来在我的应用程序前端中捕获这些字符?我可以将表拆分为一个狭窄的表,以进行快速索引和扫描,而另一个表则可以容纳其他的,不经常使用的,扩展大小的数据吗?我可以将可能的varchar数据键入类别,然后将一些数据提取到一些较小的列(可能是int或bool类型的列)中,然后以这种方式缩小varchar列吗?
您可以在这里做很多事情。最好先做一个假设,然后使用实际测量的性能数据逐步设计。祝好运。
性能?否。磁盘存储?是的,但是很便宜而且很多。除非您的数据库将增长到TB级,否则您可能还可以。
你们中有些人错误地认为a varchar(200)
在磁盘上所占的表大小比a在磁盘上所占的表大varchar(20)
。不是这种情况。只有当您超过255个字符时,mysql才会使用一个额外的字节来确定varchar
字段数据的长度。
MEMORY
。
可能会影响性能-但通常不会达到大多数用户会注意到的水平。
当预先知道每个字段的大小时,MySQL会确切知道每个字段/行之间有多少字节,并且可以在不读取所有数据的情况下进行页面前移。使用可变字符会削弱这种优化能力。
更好的是char vs varchar。
对于大多数用途,你会被罚款或者用-但有是一个区别,而对于大型数据库,是有原因的,你会选择一个或另一个。
您应该尝试在大多数情况下以与char列相同的方式查看varchar列,并保守地设置长度。您不必总是这么想var修饰符,因为它会影响最大长度上的决策。确实应该将其视为性能提示,而不是所提供的字符串长度会有所不同。
这不是必须由数据库内部严格遵循的指令,可以完全忽略它。但是请务必小心,因为有时实现可能会泄漏(例如,固定长度和填充),即使它不在理想的世界中也是如此。
如果您使用的是varchar(255),则无法保证在性能方面总是在任何情况下都与char(255)有所不同。
按照手册中有关存储要求的建议,将其设置为255、65535等似乎很容易。这给人的印象是0(是的,是东西)和255之间的任何值都会产生相同的影响。但是,这不能完全保证。
对于行存储而言,存储要求确实是真实的,或者是对于成熟持久的存储引擎的良好指示。它不能很好地指示诸如索引之类的指标。
有时候这是一个棘手的问题,确切地说,一条弦应该持续多长时间,以便将其设置为您应该知道的最大范围,但这没有影响。不幸的是,这通常留给用户解决,这确实有些武断。您真的不能说永远不要使字符串过大,因为在某些情况下您可能不确定。
您应该确保当字符串太长而不是截断字符串时,MySQL查询会引发错误,以便至少知道字符串是否因发出错误而太短。调整列大小以放大或缩小它们可能是昂贵的DDL操作,应牢记这一点。
字符集还应考虑长度和性能的影响。长度是指长度而不是字节。例如,如果使用utf8(而不是MB4),则varchar(255)实际上是varbinary(3 * 255)。如果不运行测试并深入研究源代码/文档,很难知道这样的事情将如何发挥作用。因此,存在过长的长度以产生意外膨胀的影响的可能性。这不仅适用于性能。如果您有一天需要将varchar列的字符集更改为较大的字符集,那么如果允许出现不必要的长字符串,您可能最终无济于事而无法达到要求。通常这是一个相当小众的问题,但确实存在,
如果事实证明MAX(LENGTH(column))总是<64(例如,如果确定输入的限制与列定义不匹配),但是您有varchar(255),则有一个您很有可能会使用比某些情况下所需空间多四倍的空间。
这可能包括:
根据经验,实际上不需要使varchar的长度超过需要的长度,无论是否存在性能问题,因此我建议您在可能的情况下坚持使用。理想的方法是花更多的精力来采样数据大小,实施真正的限制或通过询问/研究找出真正的限制。
当您无法执行此操作时,如果您想对不确定的情况执行诸如varchar(255)之类的操作,那么我建议您进行科学操作。这可能包括复制表,减小var char列的大小,然后将数据从原始表复制到表中以及查看索引/行数据的大小(也对列进行索引,也可以尝试将其用作主键,在InnoDB中,行为可能会有所不同,因为行是按主键排序的)。至少通过这种方式,您将知道您是否会对IO产生影响,而IO往往是最敏感的瓶颈之一。测试内存使用情况比较困难,很难对其进行详尽的测试。我建议测试潜在的最坏情况(在内存结果中有很多中间查询,请向大型临时表进行解释,等等)。
如果您知道表中不会有太多行,就不会将列用于联接,索引(尤其是复合,唯一)等,那么您很可能不会遇到很多问题。
VARCHAR(255) utf8mb4
具有约15万行的单个索引列的表的大小为11.5MB。VARCHAR(48) utf8mb4
具有相同数据(最大长度为46个字符)的索引列的表使用4.5MB。在查询中并没有太大的区别,它已建立索引。但是它确实与查询I / O和数据库备份之类的东西加在一起。