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

时间:2013-09-02 07:38:20

标签: php mysql sql

并提前感谢您的帮助。

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

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

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

需要考虑的事项:

  • 如果可以通过PHP和javascript读取列表并且没有进一步的复杂性,那将是很好的。
  • 该列表仅在整体检索时才有用,这就是为什么我宁愿不对它进行正则化。此外,在该列表上进行的计算有点复杂,并且已经用PHP和javascript编码,因此我不会对给定列表的元素进行任何SQL查询

另外,如果有更好的方法而不是存储它,我很想知道它们

非常感谢,祝你有个美好的一天/晚上。)

2 个答案:

答案 0 :(得分:7)

首先,你真的不想这样做。 RDBMS中的列意味着是原子的,因为它包含一条且只有一条信息。尝试在列中存储多个数据是违反第一范式的。

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

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

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

我提到你真的不想那样做吗?您需要重新考虑您的设计,以便更容易按原子行存储。例如,对该数据使用另一个表,并使用外键将其与主记录相关联。他们被称为关系数据库是有原因的。

更新:我被问及数据存储要求,就像单行在存储方面是否会更便宜一样。答案是,在典型的情况下不是没有,如果答案是肯定的,你支付的价格就不值得支付。

如果使用2列依赖表(1列用于样本所属记录的外键,一列用于单个样本)则每列最多需要16个字节(longint键列为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的书

答案 1 :(得分:2)

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

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

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

最后,这不涉及任何复杂的php-java脚本,并且很容易编写代码。