Mysql:将数据数组存储在一列中


Mysql: Store array of data in a single column

并提前感谢您的帮助。

这就是我的处境。我有一个网络系统,它根据一个由声波计创建的样本进行一些与噪音相关的计算。最初,数据库只存储这些计算的结果。但现在,我被要求自己储存样本。每个样本只是一个300或600个数字的列表,每个数字有一个小数点。

因此,我想到的最简单的方法是在表中添加一列,用于存储给定样本的所有计算。此列应包含数字列表。

那么我的问题是:将这个数字列表存储在一列中的最佳方式是什么?

需要考虑的事项:

  • 如果PHP和javascript都能读取该列表,而不会出现进一步的复杂情况,那就太好了
  • 列表只有在整体检索时才有用,这就是为什么我不想对其进行规范化。此外,对该列表进行的计算有点复杂,并且已经用PHP和javascript进行了编码,所以我不会对给定列表的元素进行任何SQL查询

此外,如果有比存储更好的方法,我很想知道他们

非常感谢,祝您度过美好的一天/晚上:)

首先,你真的不想这么做。RDBMS中的列是原子列,因为它只包含一条信息。试图在一列中存储多条数据违反了第一种正常形式

如果您绝对必须这样做,那么您需要将数据转换为可以存储为单个数据项(通常是字符串)的形式。您可以使用PHP的serialize()机制、XML解析(如果数据恰好是文档树)、json_encode()等。

但是如何有效地查询这些数据呢?答案是你不能。

此外,如果其他人在以后接管你的项目,你真的会惹恼他们,因为数据库中的序列化数据很难处理。我知道,因为我继承了这样的项目。

我有没有说过你真的不想那样做?您需要重新思考您的设计,以便更容易地将其存储在原子行中。例如,对此数据使用另一个表,并使用外键将其与主记录关联起来。它们被称为关系数据库是有原因的。

更新:有人问我数据存储需求,比如单行在存储方面是否更便宜。答案是,在典型的情况下不是,在答案是肯定的情况下,你为此付出的代价是不值得的。

如果使用2列相关表(样本所属记录的外键为1列,单个样本为1列),则每列最多需要16个字节(长键列为8个字节,双精度浮点数为8个字符)。对于100条记录,这是1600字节(忽略数据库开销)。

对于序列化字符串,在最好的情况下,在字符串中每个字符存储1个字节。你不知道这个字符串会有多长,但如果我们假设100个样本,所有存储的数据都在10000.00到99999.99之间,小数点后只有2位数字,那么每个样本就有8个字节。在这种情况下,您所节省的只是外键的开销,因此所需的存储量为800字节。

当然,这是基于很多假设的,比如字符编码总是每个字符1个字节,组成样本的字符串永远不会超过8个字符,等等

但是,当然也存在用于序列化数据的任何机制的开销。绝对最简单的方法,CSV,意味着在每个样本之间添加一个逗号。这会将n-1个字节添加到存储的字符串中。所以上面的例子现在是899字节,这是最简单的编码方案。JSON、XML,甚至PHP序列化都会添加比这更多的开销字符,而且很快就会有比1600字节长得多的字符串。所有这些都是以1字节字符编码为假设的。

如果您需要对样本进行索引,那么数据需求相对于字符串的增长将更加不成比例,因为字符串索引在存储方面比浮点列索引要贵得多。

当然,如果你的样本开始添加更多的数字,数据存储会进一步增加。39281.3392810将不能作为字符串存储在8个字节中,即使在最好的情况下也是如此。

如果数据被序列化,数据库就无法操作。你不能对样本进行排序,也不能对它们进行任何数学运算,数据库甚至不知道它们是数字!

不过,老实说,如今存储成本低得离谱,你可以花很少的钱买到多个TB的驱动器。存储真的那么关键吗?除非你有数亿条记录,否则我怀疑这是真的。

您可能想看看一本名为SQL Antipatterns 的书

我建议为示例创建一个单独的表,其中包含三列。一个是记录的id,第二个是样本的id,而第三个是值。当然,如果您的主表还没有唯一的id列,则必须创建它并将其用作外键。

我提出建议的原因是简单性和数据完整性。另一个论点是,这种结构是内存高效的,因为您将避免varchar(这也需要解析,并且有额外计算的偏移量)。

UPDATE正如GordonM和Darin在下面详细阐述的那样,内存参数不一定有效(请参阅下面的进一步解释),但也有其他反对序列化方法的原因

最后,这不涉及任何复杂的php-java脚本,并且非常直接地编写代码。