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

使用VARCHAR(3000)或TEXT有什么基本原理吗?仅仅编写VARCHAR(3000)让人感觉有些违反直觉。我已经通过Stack Overflow上的其他类似帖子,但最好获得特定于这种类型的常见消息存储的视图。


TEXT和BLOB可以存储在表外,表只有一个指向实际存储位置的指针。它存储在哪里取决于很多东西,比如数据大小、列大小、row_format和MySQL版本。 VARCHAR与表内联存储。当大小合理时,VARCHAR会更快,这取决于您的数据和硬件,您希望使用您的数据对真实场景进行基准测试。


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

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

同样由于VARCHAR构成了行的一部分,我怀疑查看该字段的查询将比使用TEXT块的查询略快。


为了澄清最佳实践:

文本格式的消息几乎总是存储为Text(它们的长度是任意的) 字符串属性应该存储为VARCHAR(目标用户名、主题等)。

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

到底是什么原因迫使这些信息不能超过3000个字符呢?如果它只是一个任意的应用程序约束(例如,对于文本框或其他东西),则在数据层使用text字段。


你能预测用户输入的时长吗?

VARCHAR(X) Max Length: variable, up to 65,535 bytes (64KB) Case: user name, email, country, subject, password TEXT Max Length: 65,535 bytes (64KB) Case: messages, emails, comments, formatted text, html, code, images, links MEDIUMTEXT Max Length: 16,777,215 bytes (16MB) Case: large json bodies, short to medium length books, csv strings LONGTEXT Max Length: 4,294,967,29 bytes (4GB) Case: textbooks, programs, years of logs files, harry potter and the goblet of fire, scientific research logging

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


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

长一点的回答:

(在MySQL中)VARCHAR(3000)(或任何其他较大的限制)和TEXT之间基本上没有区别。前者将在3000个字符处截断;后者将截断到65535字节。(我在字节和字符之间做了区分,因为一个字符可以包含多个字节。)

对于VARCHAR中较小的限制,有一些优于TEXT的优点。

"smaller" means 191, 255, 512, 767, or 3072, etc, depending on version, context, and CHARACTER SET. INDEXes are limited in how big a column can be indexed. (767 or 3072 bytes; this is version and settings dependent) Intermediate tables created by complex SELECTs are handled in two different ways -- MEMORY (faster) or MyISAM (slower). When 'large' columns are involved, the slower technique is automatically picked. (Significant changes coming in version 8.0; so this bullet item is subject to change.) Related to the previous item, all TEXT datatypes (as opposed to VARCHAR) jump straight to MyISAM. That is, TINYTEXT is automatically worse for generated temp tables than the equivalent VARCHAR. (But this takes the discussion in a third direction!) VARBINARY is like VARCHAR; BLOB is like TEXT. A table with several 'large' VARCHARs could hit a limit of 64KB for the whole table definition; switching to TEXT is a simple and practical fix. (Example: (42000) Row size too large, from an Oracle dump to a MySQL dump )

反驳其他答案

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

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

TEXT和VARCHAR()的存储位置基于大小,而不是数据类型的名称。有关大型文本/blob列的记录内/记录外存储的最新讨论,请参见此。


前面的答案并没有足够强调主要问题:即使是在非常简单的查询,如

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

可能需要一个临时表,如果涉及到VARCHAR字段,则将其转换为临时表中的CHAR字段。因此,如果你的表中有500000行VARCHAR(65000)字段,这一列将使用6.5*5*10^9字节。这样的临时表不能在内存中处理,而是被写入磁盘。其影响预计将是灾难性的。

来源(包含指标):https://nicj.net/mysql-text-vs-varchar-performance/ (这是指在“标准”中处理TEXT vs VARCHAR (?)MyISAM存储引擎。其他的可能不同,比如InnoDB。)


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

Varchar的性能更强大,因为它完全从内存中运行,但如果数据太大,例如Varchar(4000),情况就不一样了。

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

Blob要慢得多,所以只有当你没有很多数据时才使用它,比如10000张图片,这将花费10000条记录。

遵循以下技巧获得最大的速度和性能:

使用varchar记录姓名,头衔,电子邮件 大数据使用文本 在不同的表格中分离文本 对一个ID(比如电话号码)使用左连接查询 如果你要使用Blob,应用与文本相同的技巧

这将使数据> 10m和最大10GB的表上的查询花费毫秒。


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

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

如果您只使用您的字段存档 你不关心数据 检索速度 你关心速度,但你会使用操作员 '%LIKE%'在您的搜索查询中,因此索引将没有多大帮助 你 无法预测数据长度的限制

而不是短信。


只是对这里这么多答案的更正,即使现在有点晚了。

MySQL可以根据它们的文档对文本字段进行完全索引。

提供的链接 https://dev.mysql.com/doc/refman/5.6/en/column-indexes.html

总的来说,写Varchar字段比写Text字段要长,但只有当你有大量的写请求时才会有影响