我在 MySQL 中有一个消息表,用于记录用户之间的消息。除了典型的 id 和消息类型(所有整数类型)之外,我需要将实际的消息文本保存为 VARCHAR 或 TEXT。我将前端限制设置为 3000 个字符,这意味着消息永远不会插入到数据库中的长度超过此长度。
使用 VARCHAR(3000) 或 TEXT 是否有理由?写 VARCHAR(3000) 有点违反直觉。我已经在 Stack Overflow 上浏览过其他类似的帖子,但如果能获得特定于这种常见消息存储类型的视图会很好。
TEXT 和 BLOB 可以通过存储在表之外,而表中只有一个指向实际存储位置的指针。它的存储位置取决于很多因素,例如数据大小、列大小、row_format 和 MySQL 版本。
VARCHAR 与表内联存储。当大小合理时,VARCHAR 会更快,其权衡会更快取决于您的数据和硬件,您希望使用您的数据对真实场景进行基准测试。
你能预测用户输入会持续多长时间吗?
VARCHAR(X) 最大长度:可变,最大 65,535 字节 (64KB) 大小写:用户名、电子邮件、国家、主题、密码 TEXT 最大长度:65,535 字节 (64KB) 大小写:消息、电子邮件、评论、格式化文本、html、代码、图像、链接 MEDIUMTEXT 最大长度:16,777,215 字节 (16MB) 案例:大型 json 正文、中短篇书籍、csv 字符串 LONGTEXT 最大长度:4,294,967,29 字节 (4GB) 案例:教科书、程序、多年的日志文件,哈利波特与火焰杯,科研记录
有关 this question 的更多信息。
只是为了澄清最佳实践:
文本格式的消息几乎总是应该存储为 TEXT(它们最终会变得任意长) 字符串属性应该存储为 VARCHAR(目标用户名、主题等)。
我知道你有一个前端限制,这很好,直到它没有。 *grin* 诀窍是将数据库与连接到它的应用程序分开。仅仅因为一个应用程序对数据进行了限制,并不意味着数据在本质上是有限的。
是什么消息本身迫使它们永远不会超过 3000 个字符?如果它只是一个任意应用程序约束(例如,对于文本框或其他内容),请在数据层使用 TEXT
字段。
magnet:
URL 的超大 URL?它们可以比 255 个字符长得多。
简短的回答:没有实用、性能或存储方面的差异。
长答案:
VARCHAR(3000)
(或任何其他大的限制)和 TEXT
之间基本上没有区别(在 MySQL 中)。前者将截断 3000 个字符;后者将在 65535 字节处截断。 (我区分 bytes 和 characters 因为一个字符可以占用多个字节。)
对于 VARCHAR
中的较小限制,与 TEXT
相比有一些优势。
“更小”表示 191、255、512、767 或 3072 等,具体取决于版本、上下文和字符集。
INDEX 限制了可以索引的列的大小。 (767 或 3072 字节;这取决于版本和设置)
由复杂 SELECT 创建的中间表以两种不同的方式处理 - MEMORY(更快)或 MyISAM(更慢)。当涉及“大”列时,会自动选择较慢的技术。 (8.0 版中有重大变化;所以这个项目符号可能会发生变化。)
与上一项相关,所有 TEXT 数据类型(与 VARCHAR 相对)都直接跳转到 MyISAM。也就是说,对于生成的临时表,TINYTEXT 自动比等效的 VARCHAR 更差。 (但这会将讨论引向第三方!)
VARBINARY 类似于 VARCHAR; BLOB 就像 TEXT。
反驳其他答案
最初的问题问了一件事(使用哪种数据类型);接受的答案回答了其他问题(非记录存储)。这个答案现在已经过时了。
当这个线程开始并回答时,InnoDB 中只有两种“行格式”。不久之后,又引入了两种格式(DYNAMIC
和 COMPRESSED
)。
TEXT
和 VARCHAR()
的存储位置基于 size,而不是 数据类型名称。有关大型文本/blob 列的开/关存储的更新讨论,请参阅this。
免责声明:我不是 MySQL 专家……但这是我对这些问题的理解。
我认为 TEXT 存储在 mysql 行之外,而我认为 VARCHAR 存储为行的一部分。 mysql 行有一个最大行长度.. 所以你可以通过使用 VARCHAR 来限制你可以在一行中存储多少其他数据。
另外由于 VARCHAR 构成了行的一部分,我怀疑查看该字段的查询会比使用 TEXT 块的查询稍快。
varchar
列最多可以占用 9000 个字节。
TEXT
内联存储在表中。
前面的答案对主要问题的坚持不够:即使在非常简单的查询中,例如
(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
与 VARCHAR
的处理。在其他存储引擎中可能有所不同,例如 InnoDB。)
Varchar 用于电子邮件地址等小数据,而 Text 用于新闻文章等更大的数据,Blob 用于图像等二进制数据。
Varchar 的性能更强大,因为它完全从内存中运行,但如果数据太大,例如 varchar(4000)
,则不会出现这种情况。
另一方面,文本不会粘在内存中,并且会受到磁盘性能的影响,但您可以通过将文本数据分离到单独的表中并应用左连接查询来检索文本数据来避免这种情况。
Blob 的速度要慢得多,因此只有在您没有太多数据(如 10000 张图像,这将花费 10000 条记录)时才使用它。
请遵循以下提示以获得最大速度和性能:
对姓名、标题、电子邮件使用 varchar 对大数据使用 Text 将不同表中的文本分开 对 ID(例如电话号码)使用 Left Join 查询 如果您要使用 Blob,请应用与 Text 中相同的提示
这将使查询在数据 >10 M 并且保证大小高达 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 字段要长,但只有在您有大量写入请求时才重要
不定期副业成功案例分享