在mysql数据库中存储序列化数据应该使用什么列类型?

52

在MySQL数据库中存储序列化数据应该使用哪种列类型?我知道可以使用VARBINARY、BLOB和TEXT。哪种类型被认为是最好的,为什么?

编辑: 我知道存储序列化数据不太好,但是在这个特定的情况下我需要这样做。如果你有答案,请相信我并专注于问题本身。谢谢!


5
我明白通常不应该使用它。这是一个特殊情况,实际上使用它是有道理的。 - djburdick
8个回答

68

回答:在许多数据库管理系统中,text已经被弃用,因此最好使用一个具有高限制的blob或varchar(而且如果使用blob,则不会出现任何编码问题,这是varchar和text所存在的主要麻烦)。

此外,正如MySQL论坛上的这个帖子所指出的那样,硬盘比软件便宜,因此您最好先设计您的软件并使其运行,只有当空间成为问题时,您可能需要优化该方面。因此,不要试图过早地过度优化列的大小,最好首先将大小设置得更大(这还将避免安全问题)。

关于各种评论:

这里有太多SQL迷了。尽管我非常喜欢SQL和关系模型,但它们也有缺点。

将序列化数据原样存储到数据库中(例如存储JSON或XML格式的数据)有一些优点:

  • 您可以获得更灵活的数据格式:随时添加和删除字段、随时更改字段规范等等…
  • 与对象模型的阻抗匹配较小:您存储和检索数据就像它在程序中一样,与检索数据并且必须在程序对象结构和关系数据库结构之间进行处理和转换相比。

还有许多其他优点,请勿偏执地认为只有关系数据库是伟大的工具,我们可以使用其他工具。更多的工具,更好。

至于一个具体的用例,我倾向于在我的数据库中添加一个JSON字段来存储记录的额外参数,其中JSON数据的列(属性)将永远不会单独SELECT,而只有在选择正确的记录时才会使用这些额外参数。在这种情况下,我仍然可以使用关系列来区分我的记录,并且当选择正确的记录时,我可以随意使用额外的参数。

建议保留两者优点(速度、可序列化和结构灵活性),只需使用几个标准的关系列作为唯一键来区分行,然后使用 blob/varchar 列插入序列化数据。通常,只需要两三个列作为唯一键,因此这不会成为主要负担。

此外,您可能会对 PostgreSQL 感兴趣,它现在具有 JSON 数据类型,以及 PostSQL 项目,可以像处理关系列一样直接处理 JSON 字段。


7
总是有某种使用情况,所以最好避免像“不要那样做”的回答。我这么说是因为我刚读了一个帖子,其中有人建议永远不要在关系型数据库中存储JSON数据。然而,正如你指出的那样,如果数据不会被选择并且您想要对存储的数据具有灵活性,我认为将JSON字符串存储到数据库中没有错。点赞表示指出了这个情况...很好的答案! - Savas Vedova

11

你打算存储多少数据?请查看MySQL文档中字符串类型和它们的大小规格。关键在于你不需要对该列进行索引,但也永远不想让它溢出或被截断,否则JSON文件就无法阅读。

  • TINYTEXT 长度 < 2^8 字符
  • TEXT 长度 < 2^16 字符
  • MEDIUMTEXT 长度 < 2^24 字符
  • LONGTEXT 长度 < 2^32 字符

其中L代表字符长度。

通常来说,Text类型就足够了,但如果你要存储更多内容,就需要选择更大的类型。不过,在这种情况下,你可能不希望将其存储在数据库中。


2
我理解长度限制。我更关心博客与文本存储的优缺点。 - djburdick

10

@Twisted Pear提到的长度限制是很好的理由。

还要考虑到TEXT及其类别与字符集相关联,而BLOB数据类型则没有。如果您只是存储原始数据字节,那么可以使用BLOB而不是TEXT

请注意,您仍然可以在BLOB中存储文本数据,但不能对它执行任何涉及字符集的SQL操作; 它对SQL来说只是字节。但这可能不是您的问题,因为结构未知的序列化数据对SQL无用。你只需要存储字节并获取字节。字节的解释取决于您的应用程序。

我也曾经在使用某些客户端库(例如PHP)时遇到过使用LONGBLOBLONGTEXT出现麻烦的情况,因为客户端尝试分配与最大可能数据类型一样大的缓冲区,在任何给定行上不知道内容将有多大,直到检索到。这导致PHP试图分配4GB缓冲区而爆炸。我不知道您正在使用哪个客户端,或者它是否遭受相同的行为。

解决方法:使用MEDIUMBLOBBLOB,只要这些类型足以存储您的序列化数据。


关于有人告诉你不要这样做的问题,我不会告诉你(尽管我是SQL倡导者)。确实,您无法使用SQL表达式在序列化数据中执行操作,但这不是您的目的。将该数据放入数据库中所获得的好处包括:

  • 将序列化数据与其他更多关系型数据相关联。
  • 根据事务范围,COMMIT,ROLLBACK存储和检索序列化数据。
  • 将所有关系型和非关系型数据存储在一个地方,更容易复制到从服务器、备份和恢复等。

7

WordPress将序列化数据存储在其postmeta表中,格式为LONGTEXT。我发现WordPress数据库是研究列数据类型的好地方。

注:serialized data指序列化后的数据,它可以被存储和传输,并且可以通过反序列化还原成原始数据。


18
WordPress 应该被用作糟糕编码、糟糕实践、糟糕选择的例子。如果说有什么用处,WordPress 可以作为一个 设计应用时不该效仿的例子 - Mjh

3
我可能晚了,但是php.net关于序列化对象的文档中提到了以下内容:
请注意,这是一个可能包含空字节的二进制字符串,并且需要按此方式存储和处理。例如,serialize()输出通常应该存储在数据库的BLOB字段中,而不是CHAR或TEXT字段。
来源:http://php.net/manual/en/function.serialize.php 希望这可以帮到你!

1
截至MySQL 5.7.8,MySQL支持本地JSON数据类型:MySQL手册

-1

除非序列化数据除了从数据库中保存和恢复之外没有其他用途,否则您可能不想以这种方式处理它。

通常,序列化数据具有多个字段,应将其作为单独的列存储在数据库中。每个序列化数据项通常都是单独的列。其中一些列自然会成为关键字段。除了数据之外,还可以添加其他列来指示插入发生的日期+时间、负责用户等等。


2
嘿,沃利。谢谢,这是一个特殊情况。我知道通常不应该序列化数据。如果你能回答序列化数据的最佳列类型,那就太好了。 - djburdick

-4

我找到了:

varchar(5000)

对我们来说,它是大小/速度最佳平衡。此外,它可以处理rails 3序列化数据(varbinary),以前会不时出现序列化错误。


1
这是最好的答案吗?@djburdick有没有更灵活的方法?将日期存储为数组(键:1-31,值:日期价格)怎么样? - Josua Marcel C
1
请考虑页面对齐。4096或8192可能更好。 - EnabrenTane
我想在这个答案中看到更多的理由。是哪种类型的分析显示了这一点? - CoffeDeveloper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接