在数据库中存储集的最有效方法是什么?

时间:2013-12-22 19:25:51

标签: sql database database-design set relational-database

我希望以这样一种方式存储集合,即我可以查询与另一集合的超集,子集或相交的集合。

例如,如果我的数据库有{1,2,3},{2,3,5},{5,10,12}集,我查询它:

  • 设置{2,3}的超集应该给我{1,2,3},{2,3,5}
  • 设置{1,2,3,4}的子集应该给我{1,2,3}
  • 与{1,10,20}交叉的设置应该给我{1,2,3},{5,10,12}

2 个答案:

答案 0 :(得分:1)

由于某些集合事先是未知的(您的评论表明它们来自客户端作为搜索条件),因此您无法将预设关系“预制”到数据库中。即使你可以,这也代表了冗余,因此也存在不一致的机会。

相反,我会做这样的事情:

CREATE TABLE "SET" (
    ELEMENT INT, -- Or whatever the element type is.
    SET_ID INT,
    PRIMARY KEY (ELEMENT, SET_ID)
)

其他建议:

  • 请注意ELEMENT字段是如何位于主键的前沿。这应该有助于下面的查询比PRIMARY KEY(SET_ID,ELEMENT)更好。如果需要,你仍然可以添加后者,但如果你不这样做,那么你也应该...
  • Cluster表(如果你的DBMS支持它),这意味着整个表只是一个B-Tree(没有表堆)。这样,您可以最大限度地提高以下查询的性能,并最大限度地降低存储要求(以及缓存效率)。

然后,您可以找到等于或等于(例如)set {2,3}的集合的ID,如下所示:

SELECT SET_ID
FROM "SET"
WHERE ELEMENT IN (2, 3)
GROUP BY SET_ID
HAVING COUNT(*) = 2;

与{2,3}相交的集合如下:

SELECT SET_ID
FROM "SET"
WHERE ELEMENT IN (2, 3)
GROUP BY SET_ID;

和{2,3}的子集相同或是{2,3}的集合:

SELECT SET_ID
FROM "SET"
WHERE SET_ID NOT IN (
    SELECT SET_ID
    FROM "SET" S2
    WHERE S2.ELEMENT NOT IN (2, 3)
)
GROUP BY SET_ID;

答案 1 :(得分:0)

“Efficient”可能意味着很多东西,但规范化的方法是拥有一个包含所有可能元素的Items表和一个包含所有集合的Sets表,以及一个ItemsSets查找表。如果您在集合表中设置了A和B,那么查询(为了清晰而不是优化而这样做......)“Set”是表或字段的错误名称,因为它是关键字)

SELECT itemname FROM Items i 
WHERE i.itemname IN 
 (SELECT itemname FROM ItemsSets isets WHERE isets.setname = 'A') 
AND i.name IN 
 (SELECT itemname FROM ItemsSets isets WHERE isets.setname = 'B')
例如,那是A和B的交集(你几乎肯定可以加速它作为JOIN;再次,“高效”可能意味着许多事情,你会想要一个允许查询的架构像那样)。可以进行类似的查询以找出差异,补充,测试相等等。

现在,我知道您询问了效率,这是一种非常缓慢的查询方式,但这是表中唯一可靠的可扩展架构,而查询只是一个很容易显示表格是如何构建的。你可以做各种疯狂的事情,比如缓存交叉点,或者在一个字段中存储集合中的多个项目并处理它或者你有什么。但不要。缓存信息最终会变得陈旧;将超过字段大小中项目数量的静态限制;新元组的临时成员将被误解。

同样,“高效”可能意味着许多不同的事情,但最终,作为程序员可以理解和推理的信息架构将是最有效的。