MySQL:大型VARCHAR与TEXT?

Tom*_*Tom 824 mysql varchar text messages

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

是否有理由使用VARCHAR(3000)或TEXT?有一些关于编写VARCHAR(3000)的东西,感觉有点违反直觉.我已经浏览了Stack Overflow上的其他类似帖子,但是能够获得特定于此类公共消息存储的视图.

Min*_*ker 796

  • TEXT并且BLOB存储在表格之外,表格只有一个指向实际存储位置的指针.

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

更新无论VARCHAR或者TEXT是在线存储,或关闭记录取决于数据的大小,列大小,ROW_FORMAT和MySQL版本.它依赖于"文"与"VARCHAR".

  • "当大小合理时,VARCHAR会更快".什么是"合理"的字符数,100?1000?100000? (219认同)
  • +1:VARCHAR(存储内联)通常更快,如果频繁检索数据(大多数查询包括).但是,对于通常不检索的大量数据(即,未被任何查询引用),最好不要将数据内联存储.对于内联存储的数据,行大小有一个上限. (145认同)
  • 对于InnoDB,这个答案是不正确的.如果给定行上的值适合页面大小(16KB且每页必须至少包含两行),则VARCHAR和BLOB/TEXT都与其他列内联存储.如果字符串太大,它会溢出到其他页面.有关详细说明,请参阅http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/. (119认同)
  • @Pacerier:避免"内联"存储的确切好处是可以存储在块中的行数增加,这意味着表行在InnoDB缓冲区高速缓存中占用更少的块(更小的内存占用),并且意味着更少要传输到磁盘和从磁盘传输的块(减少的I/O).但是,如果"off off"存储的列在很大程度上不被查询引用,那么这只是一种性能优势.如果大多数查询都引用了这些"非行"列,那么这种好处很大程度上会消失.如果列适合最大行数并且经常被引用,则首选内联. (21认同)
  • 你能包括任何来源吗?你在哪里读过它?谢谢. (18认同)
  • @BillKarwin ......如果我理解正确,那么对于小文本项,InnoDB上的`varchar`和`blob` /`text`之间应该没有性能差异?那么,将每个`varchar`设为`text`类型并让DB管理内联与溢出是明智的吗? (13认同)
  • @MindStalker 2年后这总是如此吗?我依稀记得读到如果TEXT很小的话也可以内联. (4认同)
  • **此答案写为_before_ Row_format =引入了动态和压缩。** (4认同)
  • TEXT或BLOB列的数据可能存储在两个单独的表中.TEXT或BLOB的前256个字节将存储在您正在使用的表中.任何其他字节都存储在隐藏表中.隐藏表中的行长度为2000个字节.[http://dev.mysql.com/](http://dev.mysql.com/doc/refman/5.6/en/storage-requirements.html) (2认同)
  • 如果SELECT需要创建临时表,则在BLOB/TEXT的情况下,它总是在磁盘上创建.这对性能产生巨大影响 (2认同)
  • 有时正确的答案会随着时间而改变。理想情况下,不应该将反对票视为对给出过去正确答案的人的批评,相反,赞成票和反对票将使新的正确答案“冒泡”以获得最多的选票。 (2认同)

Mic*_*ins 460

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

VARCHAR(X)

案例:用户名,电子邮件,国家,主题,密码


文本

案例:消息,电子邮件,评论,格式化文本,HTML,代码,图像,链接


MEDIUMTEXT

案例:大型json体,短到中等长度的书籍,csv字符串


LONGTEXT

案例:教科书,程序,多年的日志文件,哈利波特和火炬,科研记录

  • @ andrew-barber这是我的观点.所有其他帖子都很好地解释了这些差异,但没有解释当你真正需要在两者之间作出选择时的情况.我试图指出使用varchar可预测短是一个很好的选择,使用任意长的文本是一个不错的选择. (28认同)
  • 可预测性实际上是一个侧面项目.实际上,最大预期长度应该是决定因素.你提到的更可预测的项目只是那样,因为它们*比其他项目短*. (7认同)
  • 字符限制:TINYTEXT:255; 文字:65,535; MEDIUMTEXT:16,777,215; LONGTEXT:4,294,967,29. (7认同)

Jam*_*mes 216

只是为了澄清最佳做法:

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

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

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

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

  • 我只是建立我们的新数据库,我假设没有人可能在我们的小评论框中放置超过2000个字符,然后,正如詹姆斯所说,今晚它突然"不好",因为用户通过了非常有效的评论,长度为2600个字符.我用varchar(2000)认为它不可能比这更长,我错了.所以,是的,直到它不是很好.在我们的案例中,只需要几天时间就能显现出来.下面的规则,Michael J. Calkins,我想我将从现在开始使用.消息,评论的文本. (9认同)
  • @Pacerier为了举例说明詹姆斯可能会说的"不是":例如Twitter,直到最近他对PM有140个字符的限制.他们认为它不再明智,并选择完全取消这个限制.如果他们没有提前考虑过(我很确定他们可能会这样做......)他们就会遇到上面描述的情景. (7认同)

Mic*_*son 32

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

我认为TEXT存储在mysql行之外,而我认为VARCHAR存储为行的一部分.mysql行有一个最大行长度.因此,您可以使用VARCHAR限制可以在一行中存储的其他数据量.

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

  • 行长度限制为65,535字节[http://dev.mysql.com/doc/refman/5.0/en/column-count-limit.html].如果您的列是utf8编码的,这意味着3000个字符的`varchar`列最多可能需要9000个字节. (37认同)
  • @raylu MySQL的UTF-8是"伪UTF-8",因为它每个字符最多只支持3个字节,因此无法在MySQL的UTF-8中直接存储超出BMP平面的unicode字符.这在MySQL 5.5中得到修复. (13认同)
  • UTF-8字符最多可以是4个字节,所以我认为你的意思是12,000个字节(除非有一些我不理解的MySQL事情). (7认同)
  • 我相信这个断言仅适用于MyISAM.我找不到一个明确的来源,但我相信InnoDB也会在表中存储`TEXT`内联. (2认同)
  • @dotancohen我在这里找到了一个来源,解释了使用InnoDB存储可变长度数据可能会有所不同(可以存储在外部或内联行中)http://mysqlserverteam.com/externally-stored-fields-in-innodb/ (2认同)

Ric*_*mes 25

简短回答: 没有实际,性能或存储,差异.

答案很长:

VARCHAR(3000)(或任何其他大限制)和之间基本没有区别(在MySQL中)TEXT.前者将截断为3000个字符 ; 后者将截断为65535 字节.(我区分字节字符,因为一个字符可以占用多个字节.)

对于较小的限制VARCHAR,有一些优势TEXT.

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

反驳其他答案

原始问题提出了一件事(使用哪种数据类型); 接受的答案回答了其他问题(非记录存储).那个答案现在已经过时了.

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

存储位置TEXTVARCHAR()基于大小,而不是基于数据类型的名称.有关大型text/blob列的开/关记录存储的更新讨论,请参阅此内容.

  • @KostaKontos - 感谢您的赞扬和拼写错误修复。当我发现需要更好的答案时,我会添加一个答案,即使 8 年和 800 票赞成为时已晚。 (2认同)

Max*_*Max 7

前面的答案并不足以解决主要问题:即使在非常简单的查询中也是如此

(SELECT t2.* FROM t1, t2 WHERE t2.id = t1.id ORDER BY t1.id) 
Run Code Online (Sandbox Code Playgroud)

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

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

  • InnoDB:同样适用于5.7版本.对于8.0,varchar temps是可变长度的. (3认同)