我有一个contacts表,其中包含诸如postcode、first name、last name、town、country、phone number等字段,所有这些字段都定义为VARCHAR(255),即使这些字段都不会接近255个字符。(如果您想知道,是这样的,因为Ruby on Rails迁移默认情况下将字符串字段映射到VARCHAR(255),而我从来没有费心覆盖它)。
由于VARCHAR将只存储字段的实际字符数(以及字段长度),比方说,与VARCHAR(255)相比,使用VARCHAR(16)是否有明显的优势(性能或其他方面)?
此外,这些字段中的大多数都有索引。字段上较大的VARCHAR大小是否会影响索引的大小或性能?
仅供参考,我使用的是MySQL 5。
发布于 2008-11-04 16:56:03
在存储方面,与总是存储255个字符的CHAR(255)不同,VARCHAR(255)足够智能,可以在给定行上只存储所需的长度。
但是,由于您用MySQL标记了这个问题,所以我将提到一个特定于MySQL的技巧:在将行从存储引擎层复制到SQL层时,VARCHAR字段将被转换为CHAR,以获得处理固定宽度行的优势。因此,内存中的字符串变为填充到声明的VARCHAR列的最大长度的。
当您的查询隐式地生成临时表时,例如排序或GROUP BY时,这可能会使用大量内存。如果对不需要那么长的数据使用大量VARCHAR(255)字段,这会使临时表变得非常大。
您可能还想知道,这种“填充”行为意味着,即使是使用单字节内容(例如ascii或latin1字符)存储的字符串,使用utf8字符集声明的字符串也会填充到每个字符三个字节。同样,utf8mb4字符集使字符串在内存中填充到每个字符四个字节。
因此,utf8中存储"No opinion“这样的短字符串的VARCHAR(255)在磁盘上占用11个字节(10个较低的字符集字符,外加一个字节的长度),但是在内存中占用765个字节,因此在临时表或排序结果中也是如此。
我曾经帮助过MySQL用户,他们在不知不觉中频繁创建1.5 up的临时表并填满了他们的磁盘空间。他们有很多VARCHAR(255)列,这些列实际上存储了非常短的字符串。
最好根据要存储的数据类型来定义列。正如其他人所提到的,它对实施与应用程序相关的约束有好处。但它有物理上的好处,可以避免我上面描述的内存浪费。
当然,很难知道最长的邮寄地址是什么,这就是为什么许多人选择比任何地址都长的长VARCHAR的原因。并且255是习惯的,因为它是长度可以用一个字节编码的VARCHAR的最大长度。它也是早于5.0的MySQL中的最大VARCHAR长度。
发布于 2009-08-11 19:46:16
除了设置varchar大小的大小和性能考虑因素之外(可能更重要的是,因为存储和处理每秒都变得更便宜),使用varchar(255)的缺点“仅仅是因为”降低了数据完整性。
定义字符串的最大限制是一件的好事,这样做可以防止比预期更长的字符串进入关系型数据库管理系统,并在以后从数据库中检索和解析比预期更长(更多字节)的值时,导致缓冲区溢出或异常/错误。
例如,如果您的字段接受由两个字符组成的国家缩写字符串,那么您就没有理由期望您的用户(在此上下文中是程序员)输入完整的国家名称。因为您不希望它们输入“安提瓜和巴布达”(AG)或“赫得岛和McDonald岛”(HM),所以在数据库层不允许这样做。此外,很可能一些程序员还没有RTFMed设计文档(肯定存在)来知道不要这样做。
将字段设置为接受两个字符,并让RDBMS处理它(通过截断来优雅地处理它,或者通过用错误拒绝它们的SQL来不优雅地处理它)。
没有理由超过一定长度的真实数据示例:
以此类推。
花点时间思考一下你的数据和它的局限性。如果您是一名架构师、开发人员或程序员,这毕竟是您的工作。
通过使用varchar(n)而不是varchar(255),您可以消除这样的问题:用户(最终用户、程序员、其他程序)输入出人意料的长数据之后,将再次困扰您的代码。
我并没有说您不应该在您的应用程序使用的业务逻辑代码中实现此限制。
发布于 2008-11-04 16:27:09
我和你在一起。对细节的过分关注是一种令人头疼的事情,而且价值有限。
曾几何时,磁盘是一种宝贵的商品,我们用汗水子弹来优化它。存储的价格下降了1000倍,这使得花在压缩每个字节上的时间变得不那么有价值了。
如果只使用CHAR字段,则可以获得固定长度的行。如果您为字段选择了准确的大小,这可以节省一些磁盘的实际大小。您可能会得到更密集的数据(用于表扫描的I/O更少)和更快的更新(更容易定位块中的空闲空间以进行更新和插入)。
但是,如果您高估了自己的大小,或者实际的数据大小是可变的,那么最终会浪费CHAR字段的空间。数据最终将变得不那么密集(导致更多的I/O用于大型检索)。
通常,尝试将大小放在可变字段上所带来的性能好处很小。您可以通过使用VARCHAR(255)与CHAR(x)进行比较来轻松地进行基准测试,以查看是否可以测量差异。
但是,有时候,我需要提供一个“小”、“中”、“大”的提示。因此,我使用16、64和255作为大小。
https://stackoverflow.com/questions/262238
复制相似问题