如何在关系数据库中存储和索引列表?

时间:2011-12-16 22:40:30

标签: sql sqlite database-design junction-table

我正在构建一个数据库(SQLite)来存储有关我编写的每个Mathematica脚本运行的信息。该脚本需要几个输入参数,因此我的DB有一个表,每个参数都有一列(以及其他列)。

某些输入参数是数字的列表。我对存储这些内容的第一个想法是使用联系表,如this question的接受答案中所述。但我通常使用相同的列表进行几次不同的运行。 如何查看任何给定列表是否已存在于数据库中,这样我可以重用其ID而不是再次存储它?

评论中提到的限制:

  • 列表长度没有明确的上限,但实际上它的范围是1到50左右。
  • 不同列表的数量很小,大约为10个。
  • 我实际上有3个列表参数。对于其中两个,列表中的值是非负的,双精度浮点数;对于第三个,值是这样的数字对。
  • 没有重复的条目。 (这些更精确地是,因此没有重复和订单无关紧要)
  • 我可以轻松安排列表元素按排序顺序排列。

例如:假设我的表设置如下

CREATE TABLE jobs (id INTEGER PRIMARY KEY, param1 REAL, param2_id INTEGER);
CREATE TABLE param2 (param2_id INTEGER PRIMARY KEY, value REAL);

当我运行脚本时,它设置参数,然后调用一个函数来运行计算,如下所示:

param1 = 4;
param2 = {.1, .3, .5};
runTheCalculation[param1, param2]

假设这是脚本的第一次运行,它会将以下内容插入到DB中:

jobs:   id      param1     param2_id
         1       4.0        1

param2: param2_id   value
         1           0.1
         1           0.3
         1           0.5

到目前为止,这么好。现在让我们说我用一个不同的参数再次运行脚本,

param1 = 2;
param2 = {.1, .3, .5};
runTheCalculation[]

在一个天真的实现中,这将导致数据库包含:

jobs:   id      param1     param2_id
         1       4.0        1
         2       2.0        2

param2: param2_id   value
         1           0.1
         1           0.3
         1           0.5
         2           0.1
         2           0.3
         2           0.5

但是我希望它能够查找列表{.1, .3, .5}已经在数据库中的事实,以便在第二次运行之后DB包含这个:

jobs:   id      param1     param2_id
         1       4.0        1
         2       2.0        1

param2: param2_id   value
         1           0.1
         1           0.3
         1           0.5

我可以使用哪种查询来查找表{.1, .3, .5}中已存在列表param2

如果有必要,我不反对创建其他表。或者如果除了使用更有意义的连接表之外还有一些模型,那也没关系。

3 个答案:

答案 0 :(得分:1)

如果列表很短,且列表数量相对较少,那么您只需对TBL_Lists中的列表进行排序,看看您的列表是否匹配。这是非常低效的,因为它将枚举所有存储列表以与一个存储列表进行比较。

另一种方式,在我看来更好的方法是哈希列表并将其哈希值存储在TBL_List_Hashes

散列列表需要枚举一次。

示例散列算法可能是构建所有已排序数值的字符串,统一填充,然后对连接字符串运行任何散列方法。

获取给定列表的哈希值然后从数据库中检索匹配的哈希值应该相对容易。 即使使用相对简单的带冲突的哈希算法,您也可以显着减少需要验证的列表数量,以便进行比较。

因此,如果您的哈希算法存在冲突,那么您将为每个错误匹配添加枚举(和查询)费用。

编辑:
以下是.net的相关答案 .net 3.5 List<T> Equality and GetHashCode

EDIT2:
如果您在匹配中与订单无关,则只需在散列之前标准化列表顺序 GetHashCode for a Class with a List Object

答案 1 :(得分:1)

您问:如何查看数据库中是否已存在任何给定列表?

正常的方法是使用索引,索引总是面向行的。因此,标准数据库设计建议您以某种方式需要将整个列表(规范化)放入一行。

由于您使用的是SQLLite,因此没有太多选项:

http://www.sqlite.org/datatype3.html

我推荐TEXT!您也可以索引BLOB,BLOB将节省一些空间,但TEXT可能会正常工作,而TEXT通常更方便调试和使用。尝试为您可以解析/生成的列表创建某种规范的String格式,并始终以一致的方式从数据库中INSERT / SELECT(例如,一致的舍入,预先排序,重复删除,尾随和前导零总是一致),你应该没事。

警告:这是一种低工程方法,甚至可能是“非正确的方式(TM)”,但如果它完成了工作......

答案 2 :(得分:0)

一般情况下,不要使用清单,除非你有一套非常不寻常的要求,并有足够的实践经验来预测后果。

联结表中包含的具有适当索引的多对多关系也将执行,并且更易于使用。它也更灵活。