4

并提前感谢您的帮助。

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

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

那么我的问题是:将此数字列表存储在单列中的最佳方法是什么?

需要考虑的事项:

  • 如果 PHP 和 javascript 都可以读取该列表而没有进一步的复杂性,那就太好了。
  • 该列表仅在全部检索时才有用,这就是为什么我宁愿不对其进行标准化。此外,在该列表上进行的计算有点复杂,并且已经用 PHP 和 javascript 编码,所以我不会对给定列表的元素进行任何 SQL 查询

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

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

4

2 回答 2

8

首先,你真的不想那样做。RDBMS 中的列是原子的,因为它包含一个且仅一个信息。试图在一列中存储多个数据是违反第一范式的。

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

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

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

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

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

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

于 2013-09-02T07:55:34.947 回答
2

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

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

更新正如 GordonM 和 Darin 在下面详细阐述的,内存参数不一定有效(请参阅下文以获得进一步的解释),但还有其他反对序列化方法的原因。

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

于 2013-09-02T07:45:24.233 回答