树状分类系统的数据库设计
Posted
技术标签:
【中文标题】树状分类系统的数据库设计【英文标题】:Database design of a tree-like category system 【发布时间】:2010-01-04 07:45:11 【问题描述】:我正在使用邻接列表模型来创建类别,并且效果很好。
在检索某个类别(例如电子产品)中的文章时,我还想检索子类别(例如电子产品->相机,甚至电子产品->相机->相机镜头)中的文章。
我现在的做法是从数据库中提取电子产品子类别的所有类别 ID,并在此列表中查找所有具有 category_id 的文章。
在我看来,这似乎非常低效且耗时,因为这可能会导致许多查询来检索这些子类别。
我想到的另一种方法是让每篇文章与整个类别树相关联(例如,关于相机镜头的文章也将与 MANY_MANY 表中的相机和电子产品类别相关联),当我检索所有文章时电子产品也会出现。
不过,这会在数据库中添加大量冗余数据,因为我可能必须为每篇文章存储 3 或 4 个类别。此外,它还会使诸如将文章移至另一个类别之类的操作复杂化。
这是正确的方法吗?还是有我没有想到的更好/更简单的方法?
任何帮助表示赞赏!
【问题讨论】:
你现在的做法听起来非常好,尤其是与你描述的第二种方法相比。 【参考方案1】:阅读这篇关于嵌套集建模的文章:Managing Hierarchical Data in mysql。
使用建议的技术,您可以在一个 SELECT 中获取整个树或子树。它比“普通”方法稍微复杂一些,但如果您要从表中进行大量读取,这完全值得。
【讨论】:
我喜欢这篇文章,但我有一个问题。假设我们在同一张表中有第二棵树。根的 lft 将是 21。然后我们将另一个孩子添加到前一棵树。这将导致该树的根的 rgt 与下一个根重叠。我该如何解决这个问题?我不想重新编号新插入节点右侧的所有节点。这是唯一的方法吗? 没关系。我认为关于添加新节点的部分是结论性的。不过这不是有点贵吗?如果您在表中的早期树之一中执行添加或删除,您将迭代几乎整个表以更新 lft 和 rft 值。这是否被普遍接受? 我认为您必须自己权衡一下:记录总量 * 写入量 / 读取量 是的,我们在工作中讨论过这个问题。我还发现了另一篇使用“stern-brocot 树算法”的文章,该算法承诺是非易失性的。以上是关于树状分类系统的数据库设计的主要内容,如果未能解决你的问题,请参考以下文章