MySQL的varchar(50)和varchar(500)区别?

https://juejin.cn/post/7350228838151847976

这个的话,如果说是磁盘占用其实都是一样的,比如说你一个字段为20,那么磁盘所占用的一定是20

但如果从内存占用来说,这两个就有比较大的区别的了。你把这个字段读到内存时,为这个字段申请的内存是根据varchar(xx)这东西来确定的,因为我们操作系统本身为数据申请内存,都有预申请的一个过程,一次申请多少呢。

总结的核心结论:

  • <font style="color:rgb(0, 0, 0);">VARCHAR</font>的“可变长度”特性主要体现在磁盘存储上,使其能节省空间。
  • 内存中,为了性能和简化数据读取流程,MySQL 会为 <font style="color:rgb(0, 0, 0);">VARCHAR</font>预先分配其定义的最大长度 (**<font style="color:rgb(0, 0, 0);">N</font>**) 所需的空间
  • 这种内存分配机制意味着过度定义**** **<font style="color:rgb(0, 0, 0);">VARCHAR</font>**的最大长度 (**<font style="color:rgb(0, 0, 0);">N</font>**) 会直接导致内存浪费,这种浪费是普遍存在的(不仅限于排序操作)。
  • 因此,在定义 <font style="color:rgb(0, 0, 0);">VARCHAR</font>字段时,务必根据实际业务需求,选择一个足够用但又不会过度冗余的最大长度 (**<font style="color:rgb(0, 0, 0);">N</font>**),以平衡磁盘空间节省和内存使用效率。<font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>的流行与其在单字节长度前缀下的存储效率优化有关。

  1. 磁盘存储(节省空间):
    • <font style="color:rgb(0, 0, 0);">VARCHAR</font>在磁盘上存储的是实际数据 + 一个或两个字节的长度前缀
    • 长度前缀指示了该字段值实际占用的字节数。
    • 因此,磁盘空间占用是可变的,只取决于实际存储的数据长度(加上很小的长度前缀开销)。定义的最大长度 (<font style="color:rgb(0, 0, 0);">VARCHAR(N)</font>) 只限制了能存储多少数据,不影响实际存储空间(除非数据达到最大长度)。
  2. 内存分配(固定大小):
    • 当 MySQL 从磁盘读取一行数据到内存时,它需要预先为每一列分配内存空间
    • 在读取具体数据内容之前,MySQL 只知道该列的定义:它是一个 <font style="color:rgb(0, 0, 0);">VARCHAR</font>,并且其最大允许长度是**** **<font style="color:rgb(0, 0, 0);">N</font>**字节
    • MySQL 无法在读取数据之前知道该字段在这一行中的实际长度是多少(是 10 还是 20?)。这个实际长度信息是存储在数据本身的开头(长度前缀)。
    • 为了能够安全地接收从磁盘读取出来的整行数据(包括所有列),MySQL 必须为每个 <font style="color:rgb(0, 0, 0);">VARCHAR</font>列分配足够容纳其最大可能长度 (**<font style="color:rgb(0, 0, 0);">N</font>**) 的内存空间
    • 关键原因:性能。 如果每次读取一行时,都尝试先读取长度前缀,再根据这个长度精确申请内存,然后再读取实际数据,会导致大量的、细碎的内存分配操作和额外的 I/O 定位。这会极大地降低数据读取的性能。预先按最大长度分配内存虽然可能浪费一些空间,但避免了频繁的内存申请开销,是性能与内存利用之间的权衡。
  3. 定义长度 (**<font style="color:rgb(0, 0, 0);">N</font>**) 的重要性:
    • 正因为内存分配是按定义的最大长度 (<font style="color:rgb(0, 0, 0);">N</font>) 进行的,所以 <font style="color:rgb(0, 0, 0);">VARCHAR(N)</font>中的 <font style="color:rgb(0, 0, 0);">N</font>直接影响内存消耗
    • 即使你存储的实际数据很短(比如 <font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>只存了 10 个字符),MySQL 在内存中也会为该字段预留 255 字节(或根据字符集计算出的最大字节数)的空间。
    • 过度定义**** **<font style="color:rgb(0, 0, 0);">N</font>**(如**** **<font style="color:rgb(0, 0, 0);">VARCHAR(1000)</font>**但实际只用 10 字节) 会导致严重的内存浪费。 这种浪费不仅发生在排序等需要临时表的操作中(如原文所述),也发生在任何将行数据读入内存的操作中(如简单的 <font style="color:rgb(0, 0, 0);">SELECT</font>查询、连接操作、在内存中更新数据等)。这就是为什么强调“即使不排序,也可能有其它内存不够的问题出现”。
  4. 255 字节的特殊性:
    • 长度前缀需要占用空间。对于最大长度 <font style="color:rgb(0, 0, 0);">N</font><= 255 字节的 <font style="color:rgb(0, 0, 0);">VARCHAR</font>,长度前缀只需要 1 个字节
    • 对于最大长度 <font style="color:rgb(0, 0, 0);">N</font>> 255 字节的 <font style="color:rgb(0, 0, 0);">VARCHAR</font>,长度前缀需要 2 个字节
    • 因此,<font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>是一个非常常见的定义:
      • 它充分利用了单字节长度前缀能表示的最大长度(255)。
      • 定义 <font style="color:rgb(0, 0, 0);">VARCHAR(256)</font>会导致长度前缀变成 2 字节,而实际能存储的数据只比 <font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>多 1 字节(256 vs 255),但长度前缀开销翻倍(2字节 vs 1字节)。从存储效率角度看,<font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>是单字节长度前缀下的最优选择。
      • 注意: 这里的 255/256 指的是字节数,不是字符数。对于多字节字符集(如 UTF8MB4),一个字符可能占用多个字节,<font style="color:rgb(0, 0, 0);">VARCHAR(255)</font>能存储的字符数会少于 255。