我在MySQL中有一个消息表,记录用户之间的消息。除了典型的id和消息类型(所有整数类型)之外,我需要将实际的消息文本保存为VARCHAR或text。我设置了3000个字符的前端限制,这意味着消息永远不会被插入到db中,超过这个长度。
使用VARCHAR(3000)或TEXT有什么基本原理吗?仅仅编写VARCHAR(3000)让人感觉有些违反直觉。我已经通过Stack Overflow上的其他类似帖子,但最好获得特定于这种类型的常见消息存储的视图。
我在MySQL中有一个消息表,记录用户之间的消息。除了典型的id和消息类型(所有整数类型)之外,我需要将实际的消息文本保存为VARCHAR或text。我设置了3000个字符的前端限制,这意味着消息永远不会被插入到db中,超过这个长度。
使用VARCHAR(3000)或TEXT有什么基本原理吗?仅仅编写VARCHAR(3000)让人感觉有些违反直觉。我已经通过Stack Overflow上的其他类似帖子,但最好获得特定于这种类型的常见消息存储的视图。
当前回答
前面的答案并没有足够强调主要问题:即使是在非常简单的查询,如
(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之间有一个巨大的差异。虽然VARCHAR字段可以被索引,但TEXT字段不能。VARCHAR类型字段内联存储,而TEXT则脱机存储,只有指向TEXT数据的指针实际存储在记录中。
如果你必须索引你的字段,以便更快的搜索,更新或删除,而不是使用VARCHAR,无论有多大。VARCHAR(10000000)永远不会与TEXT字段相同,因为这两种数据类型在本质上是不同的。
如果您只使用您的字段存档 你不关心数据 检索速度 你关心速度,但你会使用操作员 '%LIKE%'在您的搜索查询中,因此索引将没有多大帮助 你 无法预测数据长度的限制
而不是短信。
Varchar适用于电子邮件地址这样的小数据,而Text适用于新闻文章这样的大数据,Blob适用于图像这样的二进制数据。
Varchar的性能更强大,因为它完全从内存中运行,但如果数据太大,例如Varchar(4000),情况就不一样了。
另一方面,文本不固定在内存中,并且受到磁盘性能的影响,但是可以通过将文本数据分离到单独的表中并应用左连接查询来检索文本数据来避免这种情况。
Blob要慢得多,所以只有当你没有很多数据时才使用它,比如10000张图片,这将花费10000条记录。
遵循以下技巧获得最大的速度和性能:
使用varchar记录姓名,头衔,电子邮件 大数据使用文本 在不同的表格中分离文本 对一个ID(比如电话号码)使用左连接查询 如果你要使用Blob,应用与文本相同的技巧
这将使数据> 10m和最大10GB的表上的查询花费毫秒。
前面的答案并没有足够强调主要问题:即使是在非常简单的查询,如
(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。)
简单的回答是:没有实用性、性能或存储方面的差异。
长一点的回答:
(在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列的记录内/记录外存储的最新讨论,请参见此。
你能预测用户输入的时长吗?
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
关于这个问题还有更多信息。