为什么数据库列的字符长度为191? - Grouparoo


有时,当您查看数据库的架构时,会看到有这样定义的文本字段:

email_address varchar(191) NOT NULL

这意味着该列支持最大长度为191个字符的字符串,并且不能为null。191是个奇数-它是从哪里来的?在这篇文章中,我们将了解在大多数关系数据库中将191个字符限制为默认值的历史原因。
 
为什是么varchar不是text呢?
您可能要问的第一个问题是,为什么要完全限制可以存储在数据库中的字符串的长度?所有现代流行的关系数据库支持(几乎)无限大小的串用text或blob型列,那么为什么不放开限制呢?原因是索引。
如果要按列进行搜索,例如说email_address,您可能想在执行以下操作时为其添加索引以加快处理速度:
select id from users where email = 'foo@example.com';

随着表变大,搜索变得越来越慢,因为数据库必须检查每一行以找到匹配项。但是,如果添加搜索索引,则将告诉您的数据库实质上是用树“预先计算”流行的搜索模式,因此下一次搜索要快得多。本质上,索引花费计算时间(和少量磁盘空间)使对数据库的写入速度变慢,从而在以后加快读取速度。对于大多数应用程序来说,这是一个很大的折衷,因为它们“重读”和“轻写”。
那么,为什么要使用varchar?如果可以假设索引存储的数据类型,则可以使索引更好地执行。知道索引中的字符串有多长时间是加快速度的最佳方法之一。对于某些数据库,不允许您将搜索索引添加到text类型的列中,因为无法完成此优化,而在其他数据库中,索引的性能将不佳。实际上,从历史上看,数据库是在建立索引以优化搜索以及将数据存储在磁盘上的方式方面受到限制的。
 
MySQL的错
好的,所以索引很好。但是,总的来说,任何大小的索引似乎都可以工作,尽管今天确实如此,但这并不总是可行的。我们看看过去默认的列大小是多少,即255个字符,例如:

email_address varchar(255) NOT NULL

MySQL是2000年代初期最流行的开源数据库,索引字段中的字符数上限为255个。关于MySQL为什么选择255个字符限制的历史是模糊的(请参阅下面的链接),但是最受欢迎的理论包括:
  • 256是您可以用8位整数表示的最大数字。MySQL非常关心速度和内存使用情况,因此希望以尽可能小的数据类型存储事物。
  • MySQL本身试图与甚至更旧的数据库(sybase / SAP)兼容,并且它们的字符数限制为255个。
  • MySQL希望确保其索引文件可以放在旧文件系统上的单个页面块中。

考虑到256个字符的限制,MySQL开发人员感到很乐于根据255个字符的限制进一步优化数据库的许多部分(稍后将对此进行更多介绍)。由于在那个时期启动了许多流行的开源应用程序框架(Wordpress,Django和Rails仅举几例),所以即使它们可以在多种数据库类型(如postgres)上运行,它们都遵循MySQL的默认值。这形成了大多数ORM(对象-关系映射-Wikipedia )要使用的通用默认值varchar(255),而与使用的数据库无关。
 
为什么不是191而是255?
255比191更好,为什么限制为191?因为表情符号,utf8mb4字符集允许包括表情符号。在2000年代初期,MySQL很高兴在varchar列中支持255个字符并对其进行索引,当时最流行的文本编码是Latin1或utf8,innodb假定3个字节足以存储每个字符,但是,现在utf8mb4需要4个字节来存储每个字符。
MySQL数据库内部innodb:只能有767个字节的索引-足以存储255个3字节字符(767/3 = 255)。这是基于了解正在索引的数据大小的索引优化的一个极端示例!因此,如果字符占用更多空间来存储,那么您可以索引的字符数必须减少。具体来说,767/4 = 191。
随着更多软件支持国际用户,默认情况下使用varchar(191)替换varchar(255)。对于不需要支持国际用户的软件应用程序,一旦用户开始期望表情符号支持(通常与智能手机的兴起相关联),则在2010年代初他们也需要升级。
 
总结
utf8mb4字符编码已成为默认设置,而固定长度索引已成为历史。但是,在许多应用程序中,我们仍然具有这些191个字符的默认值,以确保兼容性。无论如何,当索引知道它们要比较的字符串的大小时,它们仍然可以发挥最佳性能,因此出于速度原因,我们仍然希望对列长度​​进行一些限制,并且由于历史和惯性,191限制仍然存在。