3

我将 Mnesia 与 Erlang 一起使用,但这个问题适用于任何键值数据库,如 couchdb 等。

我试图摆脱 RDBMS 的思维过程,但我不知道如何有效地实现这种模式。

假设我有一个用户记录,他有很多 SubItemA 记录,其中有很多 SubItem B 记录,所以:

User
-SubItem A
--SubItem B
...

我需要对 SubItem B 运行查询。当它嵌套时这样做是否有效?我应该把它标准化,这样它会更快吗?

我听说有些人使用数据复制,所以数据既嵌套又分离,这很荒谬还是在某些情况下真的有用?

4

4 回答 4

3

潜在的问题是,什么时候性能足够好

如果您确实需要详细检查每个 SubItem B 并且 B 的大小决定了字典的整体大小,那么对 User 字典进行表扫描不会产生过多的开销。

如果这还不够好,请将其规范化,以便在查询 SubItem B 时避免预先读取所有 User 和 SubItem A 数据。在 SubItem B 中使用复合键,例如 (UserId, SubItemAId, SubItemBId)字典,如果表是有序的,那么您可以进行范围查询。

如果这完全破坏了您的 User/SubItem A 查询性能,那么将数据复制作为最后的手段,因为它更容易出错。

于 2009-03-03T19:36:07.003 回答
1

在 CouchDb 中,为每个 SubItems 发出视图条目是微不足道的。这将使您可以非常快速地访问这些项目。根据您还放入视图条目的内容,您可能会提供链接回父文档/子项目所需的任何信息。

于 2009-03-04T17:51:19.383 回答
1

我不确定 Mnesia,而且我才刚刚开始使用 CouchDB,但我的理解是,在 CouchDB 中,由于您生成自己的自定义索引(“视图”),因此您可以直接在这些子上构建索引项目。

示例地图功能:

function(doc) {
    for(var i in doc.subitems_a) {
        var subitem_a = doc.subitems_a[i];

        for(var j in doc.subitems_a[item_a].subitems_b) {
            var subitem_b = subitem_a.subitems_b[j];

            emit(subitem_b, doc)
        }
    }
}

这实际上是子项 B 的索引列表,然后您可以根据选择从该列表中剪切和拼接。

于 2009-03-04T17:55:01.247 回答
0

实际上,我认为这取决于您使用的数据库。在 CouchDB 中,一件事会更好,而在 Mnesia 中,另一件事会更好。您应该对数据进行分区和分片吗?你应该按照什么标准这样做?多少数据重复才足够?

正如 Jeffery Hantin 所说,需要进行一些实验和分析才能找出正确的解决方案。也就是说,大多数非关系数据库都为您提供了解决问题所需的工具。你的职责是弄清楚每一个的权衡,以及你可以接受的权衡与其他权衡。

于 2009-05-08T03:36:03.530 回答