【问题标题】:varchar(20) and varchar(50) are same?varchar(20) 和 varchar(50) 是一样的吗?
【发布时间】:2012-06-23 08:17:09
【问题描述】:

我看到评论“如果在 varchar(20) 列中有 5000 万个介于 10 到 15 个字符之间的值,并且在 varchar(50) 列中有相同的 5000 万个值,它们将占用完全相同的空间。那就是varchar 的全部意义,而不是 char。”。谁能告诉我原因?见What is a reasonable length limit on person "Name" fields?

【问题讨论】:

  • 它施加了一个逻辑限制(例如,BO 规则或“安全”)。请搜索 SO - 它之前出现过,通常以一场激烈的辩论结束。
  • @rabudde:你确定吗?能给个参考吗?如果将定义的长度放入索引或 varchar 列中,我会非常感到惊讶(现在 char 是另一回事)。据我所知,没有任何 DBMS 将完整长度存储在索引中 - 但是 MySQL 总是能带来惊喜。
  • @pst, a_horse_with_no_name:你说得对,我对另一个事实(UTF8 和索引)感到困惑,这正是重点,太大的varchar 长度会导致性能不佳对临时表进行排序或操作(在 O`Reilly 的高性能 MySQL 中引用)
  • 我认为副本很合适,尽管它是基于 varchar(255) 的减少。它还避免了其他链接问题的一些仅以性能为导向的答案。

标签: mysql varchar


【解决方案1】:

MySQL 提供多种存储引擎选择。数据的物理存储取决于存储引擎。

VARCHAR 的 MyISAM 存储

在 MyISAM 中,VARCHARs 通常只占用字符串的实际长度加上一两个字节的长度。这是因为 MyISAM 的设计限制为表锁定而不是行锁定功能。性能后果包括更紧凑的缓存配置文件,但记录偏移量的计算也更复杂(更慢)。

(事实上,MyISAM 为您提供了固定物理行大小和可变物理行大小表格式之间的a degree of choice,具体取决于整个表中出现的列类型。VARCHAR 的出现仅改变了默认方法,但存在TEXT blob 强制 VARCHARs 在同一个表中也使用可变长度方法。)

物理存储方法对于索引尤其重要,这与表不同。 MyISAM 对 both CHARVARCHAR 列使用空间压缩,这意味着在这两种情况下,较短的数据在索引中占用的空间较少。

VARCHAR 的 InnoDB 存储

InnoDB 与当前大多数其他关系数据库一样,使用更复杂的机制。 VARCHAR 最大宽度小于 768 字节的列将被内联存储,保留的空间与该最大宽度匹配。更准确的说here

对于每个非 NULL 变长字段,记录头包含 以一或两个字节为单位的列长度。两个字节只会 如果列的一部分存储在溢出页的外部或 最大长度超过255字节,实际长度超过127 字节。对于外部存储的列,两字节长度表示 内部存储部分的长度加上指向的 20 字节指针 外部存储的部分。内部部分是768字节,所以 长度为 768+20。 20字节的指针存储的真实长度 列。

InnoDB 目前不在其索引中进行空间压缩,与上述 MyISAM 正好相反。

回到问题

然而,以上所有只是一个实现细节,甚至可能在版本之间发生变化。 CHARVARCHAR 之间的真正区别在于语义,VARCHAR(20)VARCHAR(50) 之间的区别也是如此。通过确保无法将 30 个字符的字符串存储在 VARCHAR(20) 中,该数据库使各种处理器和应用程序的生活变得更轻松,更好地定义了它应该集成到可预测行为解决方案中的各种处理器和应用程序。这是个大问题。

具体到个人姓名,this question 可能会给你一些实用的指导。无论如何,全名超过 70 个 UTF-8 字符的人都会遇到麻烦。

【讨论】:

    【解决方案2】:

    是的,这确实是 VARCHAR 的重点。它只占用与文本长度一样多的空间。

    如果你有 CHAR(50),无论数据有多短(它会被填充,通常是空格),它都会占用 50 个字节(或字符)。

    谁能告诉我原因?

    因为人们认为存储大量无用的填充很浪费,所以他们发明了 VARCHAR。

    【讨论】:

    • 它实际上比“无用的填充”复杂一点:如何在 CHAR(4) 中区分 'foo''foo '
    • 是的。有点。这对某些人来说可能很重要。当我提出这个问题时,我总是得到很多反对意见(通常是在 Oracle 决定将空字符串视为 NULL 的情况下),但我质疑需要区分 'foo''foo ' 的应用程序设计(你可以从这个评论线程中看到,引号也可以是一个可能的解决方案,或者你可以用其他没有使用的东西填充)。
    • 对 CHAR 提出积极的看法:它允许固定长度的记录。对于某些特殊用途的应用程序可能很重要。
    • IMO 发帖人想知道varchar(20)varchar(50) 之间的区别,而不是“为什么varchar 发明?”
    • @rabudde 我认为 mysql 中可能存在一些用于 varchar 的数据块。这意味着 MySql 我为所有小于 32 的 varchar 分配 32 个字节,它将为所有小于 64 字节的 varchar 分配 64 个字节,等等。如果是这样,varchar(33) 和 varchar(63) 将是相同的。
    【解决方案3】:

    The manual 状态:

    CHAR 和 VARCHAR 类型的声明长度表示要存储的最大字符数。 (...)

    与 CHAR 相比,VARCHAR 值存储为一个字节或两个字节长度的前缀加上数据。长度前缀表示值中的字节数。如果值需要不超过 255 个字节,则一列使用一个长度字节,如果值可能需要超过 255 个字节,则使用两个长度字节。

    请注意,VARCHAR(255) 与 VARCHAR(256) 相同。

    这是理论。正如 habeebperwad 建议的那样,一行 的实际占用空间取决于(引擎)页面大小和(硬盘)块大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-15
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 2010-11-18
      相关资源
      最近更新 更多