【发布时间】:2011-07-29 12:30:28
【问题描述】:
应该使用什么列类型将序列化数据存储在 mysql 数据库中? 我知道你可以使用 varbinary、blob、text。什么被认为是最好的,为什么?
编辑: 我知道存储序列化数据并不“好”。不过,我需要在这种情况下这样做。请相信我,如果你有答案,请专注于这个问题。谢谢!
【问题讨论】:
-
我知道你通常不应该使用它。这是一个真正有意义的特殊情况。
应该使用什么列类型将序列化数据存储在 mysql 数据库中? 我知道你可以使用 varbinary、blob、text。什么被认为是最好的,为什么?
编辑: 我知道存储序列化数据并不“好”。不过,我需要在这种情况下这样做。请相信我,如果你有答案,请专注于这个问题。谢谢!
【问题讨论】:
除非序列化的数据除了从数据库中保存和恢复之外没有其他用途,否则您可能不希望这样做。
通常,序列化数据有几个字段,这些字段应该作为单独的列存储在数据库中。序列化数据的每一项通常都是单独的列。其中一些列自然是关键字段。除了数据之外,可能还会添加其他列以指示插入发生的日期+时间、负责的用户等。
【讨论】:
您打算存储多少?查看string types at the MySQL docs 及其sizes 的规格。这里的关键是你不关心索引这个列,但你也不希望它溢出并被截断,因为那时你的 JSON 是不可读的。
其中L是字符长度
简单的文本就足够了,但如果你要存储更多,那就更大。不过,在这种情况下,您可能不想将其存储在数据库中。
【讨论】:
长文本
Wordpress 将序列化数据作为 LONGTEXT 存储在其 postmeta 表中。我发现 Wordpress 数据库是研究列数据类型的好地方。
【讨论】:
@Twisted Pear 提到的长度限制是很好的理由。
还要考虑TEXT 及其同类具有与之关联的字符集,而BLOB 数据类型则没有。如果您只是存储数据的原始字节,您不妨使用BLOB 而不是TEXT。
请注意,您仍然可以将文本数据存储在 BLOB 中,只是不能对其执行任何考虑字符集的 SQL 操作;它只是 SQL 的字节。但这在您的情况下可能不是问题,因为它是序列化数据,其结构对 SQL 来说是未知的。您需要做的就是存储字节并获取字节。字节的解释取决于您的应用程序。
我在使用 LONGBLOB 或 LONGTEXT 使用某些客户端库(例如 PHP)时也遇到了麻烦,因为客户端尝试分配尽可能大的数据类型的缓冲区,但不知道内容会有多大任何给定的行,直到它被提取。这导致 PHP 在尝试分配 4GB 缓冲区时起火。我不知道您使用的是什么客户端,也不知道它是否存在相同的行为。
解决方法:使用MEDIUMBLOB 或只使用BLOB,只要这些类型足以存储您的序列化数据即可。
关于人们告诉你不要这样做的问题,我不会告诉你(尽管我是 SQL 倡导者)。的确,您不能使用 SQL 表达式对序列化数据中的单个元素执行操作,但这不是您的目的。通过将该数据放入数据库,您可以获得的好处包括:
【讨论】:
我找到了:
varchar(5000)
为我们实现尺寸/速度的最佳平衡。此外,它适用于 rails 3 序列化数据(varbinary)间歇性抛出序列化错误。
【讨论】:
回答:文本在很多 DBMS 中似乎已被弃用,因此最好使用具有上限的 blob 或 varchar(并且使用 blob 您不会遇到任何编码问题,这是 varchar 的主要麻烦和文字)。
正如this thread at the MySQL forums 中所指出的,硬盘驱动器比软件便宜,因此您最好先设计您的软件并使其工作,然后只有当空间成为问题时,您才可能需要优化这方面。所以不要试图过早地过度优化列的大小,最好一开始就将大小设置得更大(另外这样可以避免安全问题)。
关于各种 cmets: 这里有太多的 SQL 狂热。尽管我非常喜欢 SQL 和关系模型,但它们也存在缺陷。
将序列化数据按原样存储到数据库中(例如存储 JSON 或 XML 格式的数据)有几个优点:
还有更多其他优势,所以请不要狂热:关系数据库是一个很棒的工具,但我们不要放弃我们可以获得的其他工具。工具越多越好。
作为一个具体的使用示例,我倾向于在我的数据库中添加一个 JSON 字段来存储记录的额外参数,其中 JSON 数据的列(属性)永远不会被单独选择,但仅在以下情况下使用已选择正确的记录。 In this case, I can still discriminate my records with the relational columns, and when the right record is selected, I can just use the extra parameters for whatever purpose I want.
所以我的建议是保留两全其美(速度、可序列化性和结构灵活性),只需使用一些标准关系列作为唯一键来区分您的行,然后使用 blob/varchar 列将插入序列化数据。通常,唯一键只需要两/三列,因此这不会是主要开销。
此外,您可能对现在具有 JSON 数据类型的 PostgreSQL 以及将 JSON 字段直接处理为关系列的 PostSQL project 感兴趣。
【讨论】:
从 MySQL 5.7.8 开始,MySQL 支持原生 JSON 数据类型:MySQL Manual
【讨论】:
我可能迟到了,但是关于序列化对象的 php.net 文档声明如下:
请注意,这是一个二进制字符串,可能包含空字节,并且 需要这样存储和处理。例如,序列化() 输出通常应存储在数据库的 BLOB 字段中, 而不是 CHAR 或 TEXT 字段。
来源:http://php.net/manual/en/function.serialize.php
希望对您有所帮助!
【讨论】: