6

我正在为用作更大系统基础的组层次结构进行数据库设计。每个组可以包含其他组,也可以包含“设备”作为叶对象(设备下方没有任何内容)。

正在使用的数据库是 MS SQL 2005。(虽然在 MS SQL 2000 中工作将是一个好处;不幸的是,需要 MS SQL 2008 的解决方案目前不可行)。

有不同类型的组,这些组需要是动态的,并且用户可以在运行时定义。例如,组类型可能是“客户”、“帐户”、“城市”或“建筑物”、“楼层”,并且每种类型将具有一组不同的属性,可由用户定义。还将应用业务规则-例如,“楼层”只能包含在“建筑物”组下,并且再次,这些可以在运行时定义。

许多应用程序功能来自基于这些组运行报告,因此需要一种相对快速的方法来获取某个组(和所有子组)中包含的所有设备的列表。

使用修改的预排序树遍历技术存储组的优点是速度快,但缺点是相当复杂和脆弱 - 如果外部用户/应用程序修改数据库,则有可能完全损坏。我们还实现了一个 ORM 层,这种方法似乎在大多数 ORM 库中使用关系变得复杂。

使用公用表表达式和“标准”id/parentid 组关系似乎是避免运行多个递归查询的有效方法。这种方法有什么缺点吗?

至于属性,存储它们的最佳方式是什么?一张又长又窄的桌子,与小组有关?是否应该将通用属性(例如“名称”)存储在组表中,而不是属性表中(很多时候,名称将是显示所需的全部内容)?

使用这种方法是否会出现性能问题(假设在合理的硬件上(例如四核 Xeon 2 Ghz、4GB ram)上平均有 2000 个组,每个组平均有 6 个属性,平均有 10 个并发用户,折扣任何其他过程)?

随意提出与我在这里概述的完全不同的架构。我只是想说明我关心的问题。

4

4 回答 4

3

我建议您实际上构建最容易维护的方式(“标准”父/子设置)并至少在其上运行一些基本基准。

您会惊讶于数据库引擎可以通过正确的索引来做什么,尤其是当您的数据集可以放入内存时。

假设每组 6 个属性、2000 个组和 30 个字节/属性,那么您说的是 360KB*expected items/group——图 400KB。如果您希望每个组有 1000 个项目,那么您只会查看 400MB 的数据——这将毫无问题地放入内存中,并且当所有数据都在内存中时,数据库的连接速度很快

于 2008-09-22T02:26:12.963 回答
2

公用表表达式将让您获得具有父子关系的组列表。 是一个将 CTE 用于不同应用程序的存储过程示例。它相当有效,但请注意以下警告:

  1. 如果一个部件在层次结构中出现多次,它将在每个位置进行报告。您可能需要对结果进行后处理。
  2. CTE 有点迟钝,并且提供有限的范围来过滤查询中的结果 - CTE 可能不会在 select 语句中出现多次。

Oracle 的 CONNECT BY 更加灵活,因为它不像 CTE 那样对查询结构施加几乎那么多的限制,但是如果您使用的是 SQL Server,这将不是一个选项。

如果您需要对中间结果做一些聪明的事情,那么编写一个使用 CTE 将原始查询放入临时表并从那里处理的存储过程。SELECT INTO 将减少由此产生的流量。结果表将在缓存中,因此对它的操作将相当快。

一些可能的物理优化可能会有所帮助:

  • 父节点上的聚集索引,以便为父节点取出子节点​​使用更少的 I/O。
  • 大量 RAM 和(取决于 BOM 表的大小)具有更多 RAM 的 64 位服务器,以便主 BOM 表可以缓存在核心中。在 32 位操作系统上,/3G 引导开关是您的朋友,对于数据库服务器没有真正的缺点
  • DBCC PINTABLE 可以帮助强制数据库管理器将表保存在高速缓存中。

Parent-Attribute Type-Attribute 编码表不能很好地与 CTE 配合使用,因为如果包含属性表,您的行数将出现组合爆炸。这将排除查询中过滤属性的任何业务逻辑。将属性直接存储在 BOM 表条目上会更好。

于 2008-09-22T12:10:37.227 回答
1

Pre-order Tree Traversal 非常方便。您可以通过使用触发器使遍历数保持最新来使其健壮。

我使用的一种类似技术是保留一个单独的 (ancestor_id, descendant_id) 表,其中列出了所有祖先和后代。这几乎与预购遍历数一样好。

使用单独的表很方便,因为即使它引入了额外的连接,它确实消除了单独表的复杂性。

于 2008-09-22T13:10:55.520 回答
1

修改后的预购本质上是 Joe Celko 的 Nested Sets 方法。他的书“树和层次结构...”涵盖了邻接表和 NS,并描述了它们各自的优缺点。通过适当的索引,邻接表的 CTE 可以获得最平衡的性能。如果您主要阅读,那么 NS 会更快。

您似乎在描述的是物料清单处理器。虽然不是 M$,但 Graeme Birchall 有一本免费的 DB2 书籍,其中有一章是关于使用 CTE 进行层次结构处理的(语法几乎相同,IIRC,因为 ANSI 语法采用了 DB2,然后 M$ 采用了):http://mysite .verizon.net/Graeme_Birchall/cookbook/DB2V95CK.PDF

于 2008-09-22T17:05:08.967 回答