当前位置: 首页 > article >正文

Mysql中表字段VARCHAR(N)类型及长度的解释

 本文将针对MySQL 中 varchar (N)类型字段的存储方式进行解释,主要是对字符和字节的关系的理解。

 1. varchar (N) 中的 N

  • varchar (N) 中的 N 表示字符数,而不是字节数。这意味着 `N` 表示你可以存储多少个字符。

   字符数:指的是字符的个数,而不是这些字符在存储中所占的字节数。

   例如,varchar (255)意味着可以存储最多 255 个字符。

 2. 字符与字节的关系

  • VARCHAR字段的实际存储大小会受到字符集(如 UTF-8)影响。UTF-8 编码对于不同字符有不同的字节占用。
  •  常见字符(如英文字母、数字)占用 1 字节。
  • 一些 Unicode 字符(例如汉字、表情符号等)则需要 3 字节或 4 字节。

   - 如果你使用 UTF-8 编码,一个汉字通常占用 3 个字节。因此,varchar (255) 对于汉字来说,可以存储 255 个汉字,而如果是英文字符,可以存储 255 个字符,且每个字符占 1 字节。

3. VARCHAR`存储长度的计算

  • 存储长度:MySQL 会使用不同的字节数来存储 VARCHAR 的长度信息,具体如下:
  •  如果 N < 256,MySQL 会使用 1 字节来存储该字段的长度。
  •  如果 N >= 256,MySQL 会使用 2 字节来存储字段长度。

 这是为了节省存储空间。对于较小的 N,1 字节就足够表示长度;而对于较大的 N,2 字节可以表示更大的长度值。

    这里会有同学问,为什么 如果 N < 256,MySQL 会使用 1 字节 来存储该字段的长度。 如果 N >= 256,MySQL 会使用 2 字节 来存储字段长度?是规定好的么?

    是的,MySQL 对 VARCHAR`类型字段的长度存储采用了这样的设计,是为了在性能与空间优化之间取得平衡。这种机制的设计有以下几个原因:

 1.空间效率

      存储的长度指的是记录在表中实际数据的长度信息(即字符串的实际长度)。MYSQL需要用某种方式记录每个varchar字段的长度,因为varchar是可变的长度的类型。

      如果N<256时,最长只能记录255个字符,那么使用一个字节(8位)来存储长度信息就足够了。1字节可以标识0~255之间的数字。

      如果 `N >= 256`,则可能需要表示的长度会大于 255 个字符,这时 MySQL 使用 **2 字节** 来记录长度信息。2 字节可以表示的数字范围是 0 到 65535。

      这种机制可以有效节省存储空间。对于大部分使用 varchar 字段的场景,字段长度通常小于 256 个字符,因此只需 1 字节来存储长度,避免了使用 2 字节造成的额外空间浪费。

  2.性能考虑

     使用 1 字节表示长度时,MySQL 在读取和处理数据时所需的资源更少,读取速度会更快。
     当 N < 256 时,直接使用 1 字节来存储长度信息,不仅减少了存储所需的内存或磁盘空间,也加快了操作速度,因为处理较小的数据量会提升效率。

 3. 符合常见的数据使用模式

     在实际应用中,许多字符串数据(如姓名、邮件地址等)长度通常较短,常见字段长度往往小于 256 个字符。因此,使用 1 字节足以满足大多数场景的需求,而 2 字节则适用于存储长字符串数据的特殊场景。
     这种划分基于常见的数据使用模式,既能在存储小数据时提高效率,又能在需要时扩展到较大的字段长度。

**例子说明**
       如果你有一个 VARCHAR(100) 字段,存储的数据最多不超过 100 个字符。对于这个字段,MySQL 会使用 1 个字节来记录它的实际长度(0-255 之间的数),这意味着只需 1 字节就可以表示这个字段中字符串的长度。
       如果你有一个 `VARCHAR(300)` 字段,存储的数据可以超过 255 个字符。为了能记录所有可能的长度(0-300),MySQL 必须使用 2 个字节来存储长度信息,因为 1 字节不能表示超过 255 的数字。

结论:
     MySQL 的这一设计是规定好的,目的是在性能和空间使用之间做出折中。对于大多数应用场景,短文本占主导,因此 1 字节表示长度足够高效;而在需要更长文本的情况下,使用 2 字节也可以处理更大范围的字符长度。 

 4.存储限制与内存操作

     - MySQL 中的每个表中,所有 varchar字段的最大总字节数限制是65535 字节。
     - 在查询、排序或创建临时表时,MySQL 会基于 VARCHAR 的实际字节数来计算内存使用。
     - 因此,VARCHAR(255) 如果用于存储汉字,实际的内存占用会比存储英文字符多。

 **具体实例**
假设有一个表,包含如下两个字段:

1. name: varchar(255),用于存储英文名。
2. description: varchar(255),用于存储汉字描述。

存储英文字符的情况
  假设 name 字段存储的是英文字符:"John Doe"(10个字符)。
  varchar(255) 为该字段分配了 255 字符的空间,而实际存储了 10 个字符。
  由于字符是 ASCII 编码的,英文字符只占用 1 字节,所以这个字段占用了 10 字节的存储空间。
  存储长度:MySQL 使用 1 字节来存储 `name` 字段的长度,表示 10 个字符。

存储汉字的情况
  假设 description`字段存储的是中文字符:"这是一个描述"(7个汉字)。
  在 UTF-8 编码中,每个汉字占用 3 字节。因此,`description` 实际占用了 7 * 3 = 21 字节。
  由于 varchar(255)仍然分配了 255 个字符的空间,但由于是汉字,实际的字节数更高,因此该字段占用了 21 字节来存储数据。
存储长度:MySQL 使用 1 字节来存储 description字段的长度,表示 7 个汉字。

总内存占用
   name字段占用 10 字节数据 + 1 字节长度 = 11 字节。
   description字段占用 21 字节数据 + 1 字节长度 = 22 字节。
   总共的内存占用 = 11 + 22 = 33 字节。

总结
- varchar(N) 表示存储最多 N个字符,而不是字节数,实际的字节数取决于字符集(如 UTF-8)中的字符所占字节数。
- 对于存储长度,MySQL 使用 1 字节来表示字段长度(如果 N小于 256),使用 2 字节来表示更大长度的字段。
- 存储过程中要注意字符的字节数,因为不同字符集和字符可能占用不同的字节空间,特别是对于非 ASCII 字符(如汉字)。

5、问题总结

1.只有1字节和2字节两种选择吗,再大的字节不行么?

   在 MySQL 中,varchar类型字段的长度信息只有 1 字节和 2 字节 两种选择,而不会使用更多的字节。具体原因和设计考量如下:

   1. varchar 的设计限制

     - MySQL 对 varchar字段的最大长度限制为 65535 字节。这是由 MySQL 的存储机制决定的,一个表中 varchar字段的总字节数不能超过 65535 字节。
     - 因此,使用 2 字节已经足够表示 varchar字段的最大长度:
     - 1 字节能表示的长度范围是 0 到 255(总共 256 个值)。
     - 2 字节 能表示的长度范围是 0 到 65535(总共 65536 个值)。
     - 由于 varchar字段的设计最大长度为 65535 字节,2 字节已经足以表示所有可能的长度,所以没有必要再增加字节数。

  2. 更大数据类型的选择

   如果需要存储比 varchar 更大且更长的文本数据,MySQL 提供了其他数据类型,专门用于处理超长字符串或文本数据。这些类型在存储时采用不同的机制,而不是通过增加更多字节的长度信息。以下是常用的几种更大类型:

 - TEXT类型:TEXT 数据类型允许存储更大的文本数据,分为四种变体:
     1. TINYTEXT:最大 255 字节,使用 1 字节存储长度。
     2. TEXT:最大 65535 字节,使用 2 字节存储长度。
     3. MEDIUMTEXT:最大 16 MB,使用 3 字节存储长度。
     4. LONGTEXT:最大 4 GB,使用 4 字节存储长度。

   - BLOB 类型:与 TEXT`类型相似,但专门用于存储二进制数据。BLOB 也分为 TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB`四种变体,它们的存储机制和长度信息与 TEXT类型类似。

2. 为什么不使用更多字节?

   - 效率与需求的平衡:对于varchar 字段,2 字节已经能表示所有可能的长度(最大 65535 字节),而增加更多的字节来存储长度信息会显著增加存储开销,但并不会带来额外的好处,因为 varchar 类型本身就有长度限制。
   - 更大数据类型的存在:如果应用需要存储更大规模的数据,使用 `TEXT` 或 `BLOB` 类型是更合适的选择,而不是通过增加 varchar 字段的长度来实现。

结论:
     MySQL 选择使用 1 字节 或 2 字节 来存储varchar 字段的长度信息,因为这是对varchar 类型设计的最优折衷。对于更大的数据存储需求,MySQL 提供了 `TEXT`、`BLOB` 这类数据类型,它们使用 3 字节或 4 字节来存储长度信息,满足更大的存储需求。因此,在varchar 类型中没有必要使用超过 2 字节来表示长度信息。

3.使用 TEXT 或 BLOB 类型就不会增加存储开销了么

使用 TEXT 或 BLOB`类型虽然可以存储更大的数据,但它们也会带来额外的存储开销,与 varchar 类型相比。具体来说,主要体现在以下几个方面:

1. 额外的长度信息存储
   - 与 varchar 类型类似,`TEXT` 和 `BLOB` 类型也需要存储每个字段的长度信息。不过,它们的长度信息更大,因此会导致一定的开销。
   例如:
   - TEXT类型:
     - `TINYTEXT`:最大 255 字节,使用 1 字节存储长度。
     - `TEXT`:最大 65535 字节,使用 2 字节存储长度。
     - `MEDIUMTEXT`:最大 16 MB,使用 3 字节存储长度。
     - `LONGTEXT`:最大 4 GB,使用 4 字节存储长度。
   
   - BLOB类型:
     - `TINYBLOB`:最大 255 字节,使用 1 字节存储长度。
     - `BLOB`:最大 65535 字节,使用 2 字节存储长度。
     - `MEDIUMBLOB`:最大 16 MB,使用 3 字节存储长度。
     - `LONGBLOB`:最大 4 GB,使用 4 字节存储长度。

   总结: TEXT和 BLOB的长度存储信息随着数据类型的变化需要更多的字节,而 varchar 类型最多只使用 2 字节来存储长度信息。

2. 存储和处理机制差异
   - TEXT和 BLOB数据存储的方式通常与varchar 不同。TEXT和BLOB类型是外部存储(out-of-row)类型,意味着它们的实际数据可能存储在表的外部,而不是直接存储在行数据中。这是因为它们的内容可能非常大。
   - 因为这些数据可能存储在不同的存储位置(例如,外部文件、其他存储区域),所以读取 TEXT或 BLOB类型数据时,通常会有额外的 I/O 开销,即读取或写入这些字段时可能比 VARCHAR类型更慢,尤其在涉及大量数据时。
   - VARCHAR 数据直接存储在行内,因此读取速度通常会更快。

 3. 空间开销
     - TEXT 和 BLOB类型的存储开销相较于 VARCHAR可能更大。因为:
     - varchar 只存储实际字符的字节数和长度信息(1 或 2 字节)。
     - TEXT和 BLOB在存储数据时,除了长度信息之外,还可能引入额外的空间开销,用于管理外部存储的元数据、指针等。
   
   **举个例子**:如果你存储的是非常小的文本数据(比如 10 个字符的英文字符串),使用 TEXT类型相比 VARCHAR类型可能会带来更多的存储开销,尤其是当存储的数据量非常小,TEXT类型的存储机制可能会浪费更多的空间。

 4. 性能差异
    查询效率:对于 `VARCHAR` 字段,查询性能通常较好,因为它的存储方式是行内存储,数据直接保存在行中,不需要额外的 I/O 操作。
   - 对于 TEXT和BLOB字段,虽然它们可以存储更大的数据,但查询时可能会有额外的 I/O 开销,因为 MySQL 可能需要从外部存储中读取数据(特别是当数据量非常大时)。这种存储方式更适合处理大数据量的字段,而不是小文本。

 总结:TEXT 和 BLOB 的开销

- 存储开销:TEXT 和 BLOB 类型相较于 varchar 会有额外的存储开销,特别是当字段长度较小且需要存储的小文本时。它们的长度信息存储会使用更多的字节(最多 4 字节),而且数据存储在行外可能会增加 I/O 开销。
- 性能差异:对于较小的文本数据,varchar 类型通常会更高效,因为它是内存中连续存储的,而 TEXT 和 BLOB 类型可能需要额外的 I/O 操作。
- 适用场景:TEXT 和 BLOB 更适合存储大量文本或二进制数据,比如文章、图片数据、日志等。而 varchar 则适合存储较短的字符串数据,如用户名、电子邮件地址、简单描述等。

在选择 varchar 还是 TEXT 类型时,通常需要根据数据的实际大小来决定。如果存储的数据较小,varchar 是更合适的选择;如果存储的数据量较大,且长度可能会变化较大,TEXT或 BLOB类型则更为适用。


http://www.kler.cn/news/357204.html

相关文章:

  • void关键字
  • ubuntu 20.04 网卡启用后,只有ipv6 没有 ipv4 无法上网
  • Linux_c 有名管道练习
  • Facebook Marketplace为什么无法使用的原因?
  • 树莓派刷入OpenWrt后扩容overlay的方法
  • 诺贝尔物理学奖与机器学习、神经网络:一场跨时代的融合与展望
  • Spring容器详解:BeanFactory和ApplicationContext的不同
  • spring mvc后端实现过程
  • 【计算机网络 - 基础问题】每日 3 题(四十一)
  • 字节回应实习生破坏大模型训练:确有此事 但部分报道夸大失实
  • 推荐系统 # 二、推荐系统召回:协同过滤 ItemCF/UserCF、离散特征处理、双塔模型、自监督学习、多路召回、曝光过滤
  • VUE 仿神州租车-开放平台
  • Java中的一些名词概念
  • C++服务端的配置文件库介绍
  • Linux 中文件的权限说明
  • 论线段树的调试
  • 如何保护您的服务器免受Shellshock Bash漏洞的影响
  • IDEA项目提交至SVNGIT仓库
  • 【升华】人工智能python重要库scikit-learn学习
  • 【ARM】MDK-Flex服务管理软件使用说明