884

我在 MySQL 中有一个消息表,用于记录用户之间的消息。除了典型的 id 和消息类型(所有整数类型)之外,我需要将实际的消息文本保存为 VARCHAR 或 TEXT。我将前端限制设置为 3000 个字符,这意味着消息永远不会插入到数据库中的长度超过此长度。

使用 VARCHAR(3000) 或 TEXT 是否有理由?写 VARCHAR(3000) 有点违反直觉。我已经在 Stack Overflow 上浏览过其他类似的帖子,但如果能获得特定于这种常见消息存储类型的视图会很好。

4

8 回答 8

830
  • TEXT并且BLOB 可以通过存储在表外,表中只有一个指向实际存储位置的指针。它的存储位置取决于很多因素,例如数据大小、列大小、row_format 和 MySQL 版本。

  • VARCHAR与表内联存储。VARCHAR当大小合理时速度更快,其权衡会更快取决于您的数据和硬件,您希望使用数据对真实场景进行基准测试。

于 2010-01-07T20:45:00.017 回答
506

你能预测用户输入会持续多长时间吗?

VARCHAR(X)

最大长度:可变,最多 65,535 字节 (64KB)
大小写:用户名、电子邮件、国家/地区、主题、密码


文本

最大长度: 65,535 字节 (64KB)
案例:消息、电子邮件、评论、格式化文本、html、代码、图像、链接


中文本

最大长度: 16,777,215 字节 (16MB)
案例:大型 json 正文、短到中等长度的书籍、csv 字符串


长文

最大长度: 4,294,967,29 字节(4GB)
案例:教科书、程序、多年日志文件、哈利波特与火焰杯、科研日志

有更多关于这个问题的信息。

于 2012-11-01T17:56:45.360 回答
222

只是为了澄清最佳实践:

  1. 文本格式的消息应该几乎总是存储为 TEXT (它们最终是任意长的)

  2. 字符串属性应存储为 VARCHAR(目标用户名、主题等)。

我知道你有一个前端限制,这很好,直到它没有。*grin* 诀窍是将数据库与连接到它的应用程序分开。仅仅因为一个应用程序对数据进行了限制,并不意味着数据在本质上是有限的。

是什么消息本身迫使它们永远不会超过 3000 个字符?如果它只是一个任意的应用程序约束(例如,对于文本框或其他东西),TEXT请在数据层使用一个字段。

于 2010-01-07T21:53:20.500 回答
33

免责声明:我不是 MySQL 专家……但这是我对这些问题的理解。

我认为 TEXT 存储在 mysql 行之外,而我认为 VARCHAR 存储为行的一部分。mysql 行有一个最大行长度.. 所以你可以通过使用 VARCHAR 来限制你可以在一行中存储多少其他数据。

另外由于 VARCHAR 构成了行的一部分,我怀疑查看该字段的查询会比使用 TEXT 块的查询稍快。

于 2010-01-07T20:47:02.993 回答
33

简短的回答: 没有实用、性能或存储方面的差异。

长答案:

VARCHAR(3000)或任何其他大的限制)和TEXT. 前者将截断 3000 个字符;后者将在 65535字节处截断。(我区分字节字符是因为一个字符可以占用多个字节。)

对于较小的限制VARCHAR,比TEXT.

  • “更小”表示 191、255、512、767 或 3072 等,具体取决于版本、上下文和CHARACTER SET.
  • INDEXes可以索引列的大小是有限的。(767 或 3072字节;这取决于版本和设置)
  • 由 complex 创建的中间表SELECTs以两种不同的方式处理——MEMORY(更快)或 MyISAM(更慢)。当涉及“大”列时,会自动选择较慢的技术。(8.0 版中有重大变化;所以这个项目符号可能会发生变化。)
  • 与上一项相关,所有TEXT数据类型(与 相对VARCHAR)都直接跳转到 MyISAM。也就是说,TINYTEXT生成的临时表自动比等效的VARCHAR. (但这会将讨论引向第三方!)
  • VARBINARY就像VARCHAR; BLOB就像TEXT

反驳其他答案

最初的问题问了一件事(使用哪种数据类型);接受的答案回答了其他问题(非记录存储)。这个答案现在已经过时了。

当这个线程启动回答时,InnoDB 中只有两种“行格式”。不久之后,又引入了两种格式 (DYNAMICCOMPRESSED)。

TEXT和的存储位置VARCHAR()基于大小,而不是数据类型的名称。有关大型文本/blob 列的开/关存储的更新讨论,请参阅

于 2018-06-25T16:05:44.853 回答
7

前面的答案对主要问题的坚持不够:即使在非常简单的查询中,例如

(SELECT t2.* FROM t1, t2 WHERE t2.id = t1.id ORDER BY t1.id) 

可以要求临时表,如果VARCHAR涉及字段,则转换为CHAR临时表中的字段。因此,如果您的表中有 500 000 行带有VARCHAR(65000)字段,则仅此列将使用6.5*5*10^9字节。此类临时表无法在内存中处理并写入磁盘。预计其影响将是灾难性的。

来源(带指标):https ://nicj.net/mysql-text-vs-varchar-performance/ (这里指的是“标准”(?)MyISAM存储引擎中TEXT对vs的处理VARCHAR。在其他地方可能会有所不同,例如,InnoDB。)

于 2018-06-30T21:43:27.340 回答
4

Varchar 用于电子邮件地址等小数据,而 Text 用于新闻文章等更大的数据,Blob 用于图像等二进制数据。

Varchar 的性能更强大,因为它完全从内存中运行,但如果数据太大varchar(4000),例如,则不会出现这种情况。

另一方面,文本不会粘在内存中,并且会受到磁盘性能的影响,但您可以通过将文本数据分离到单独的表中并应用左连接查询来检索文本数据来避免这种情况。

Blob 的速度要慢得多,因此只有在您没有太多数据(如 10000 张图像,这将花费 10000 条记录)时才使用它。

请遵循以下提示以获得最大速度和性能:

  1. 使用 varchar 表示姓名、标题、电子邮件

  2. 对大数据使用文本

  3. 不同表格中的单独文本

  4. 对电话号码等 ID 使用左连接查询

  5. 如果您要使用 Blob,请应用与 Text 中相同的提示

这将使查询在数据 >10 M 并且保证大小高达 10GB 的表上花费毫秒。

于 2019-04-16T23:17:44.093 回答
4

VARCHAR 和 TEXT 之间存在巨大差异。虽然 VARCHAR 字段可以被索引,但 TEXT 字段不能。VARCHAR 类型的字段是内联存储的,而 TEXT 是脱机存储的,只有指向 TEXT 数据的指针实际存储在记录中。

如果您必须索引您的字段以更快地搜索、更新或删除而不是使用 VARCHAR,无论它有多大。VARCHAR(10000000) 永远不会与 TEXT 字段相同,因为这两种数据类型在本质上是不同的。

  • 如果您仅将您的字段用于存档
  • 你不关心数据速度检索
  • 您关心速度,但您将在搜索查询中使用运算符“%LIKE%”,因此索引不会有太大帮助
  • 您无法预测数据长度的限制

而不是去文本。

于 2019-06-23T07:43:49.393 回答