代码之家  ›  专栏  ›  技术社区  ›  Tom

mysql:大varchar对文本?

  •  791
  • Tom  · 技术社区  · 15 年前

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

    使用varchar(3000)或text是否有理由?写varchar(3000)有点违反直觉。我已经阅读过其他类似的关于堆栈溢出的文章,但最好是获得特定于这种常见消息存储类型的视图。

    6 回复  |  直到 6 年前
        1
  •  783
  •   Rick James    6 年前
    • TEXT BLOB 在表外存储,表只有一个指向实际存储位置的指针。

    • VARCHAR 与表内联存储。 瓦尔查尔 当大小合理时速度更快,权衡速度更快取决于您的数据和硬件,您将希望用数据作为现实世界场景的基准。

    更新 是否 瓦卡尔 文本 是以内联方式存储的,还是根据数据大小、列大小、行\格式和MySQL版本进行记录。它确实 取决于“文本”与“varchar”。

        2
  •  439
  •   Michael J. Calkins    8 年前

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

    VARCHAR(X)

    案例: 用户名、电子邮件、国家/地区、主题、密码


    文本

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


    中间文本

    案例: 大型JSON主体、短至中等长度书籍、csv字符串


    长文本

    案例: 教科书、程序、多年的日志文件、哈利波特与火焰杯、科学研究日志

        3
  •  215
  •   pb2q    10 年前

    只是为了澄清最佳实践:

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

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

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

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

        4
  •  32
  •   Michael Anderson    15 年前

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

    我认为文本存储在mysql行之外,而varchar存储在行的一部分。mysql行的最大行长度为..因此,您可以使用varchar限制在一行中可以存储多少其他数据。

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

        5
  •  14
  •   Rick James    6 年前

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

    长回答:

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

    对于较小的限制 VARCHAR 有一些优势 文本 .

    • “较小”指191、255、512、767或3072等,取决于版本、上下文和 CHARACTER SET .
    • INDEXes 在索引列的大小方面受到限制。(767或3072) 字节 ;这取决于版本和设置)
    • 由complex创建的中间表 SELECTs 以两种不同的方式处理——内存(更快)或myisam(较慢)。当涉及“大”列时,会自动选择速度较慢的技术。(版本8.0中有重大更改;因此此项目符号项可能会有所更改。)
    • 与上一项相关,全部 文本 数据类型(与 瓦卡尔 )直接跳到Myisam。也就是说, TINYTEXT 对于生成的临时表,自动比等效的更差 瓦卡尔 . (但这把讨论带到了第三个方向!)
    • VARBINARY 就像 瓦卡尔 ; BLOB 就像 文本 .

    反驳其他答案

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

    当这个线程启动时 答:InnoDB中只有两种“行格式”。不久之后,又有两种格式( DYNAMIC COMPRESSES )介绍。

    的存储位置 文本 VARCHAR() 基于 大小 ,而不是 数据类型名称 . 对于一个 更新的 关于大文本/BLOB列的开/关记录存储的讨论,请参见 this .

        6
  •  5
  •   Gerry    6 年前

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

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

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

    来源(带指标): https://nicj.net/mysql-text-vs-varchar-performance/ (这是指处理 TEXT VS 瓦卡尔 在“标准”中(?)Myisam存储引擎。其他方面可能不同,例如InnoDB。)