层次结构与许多表
Posted
技术标签:
【中文标题】层次结构与许多表【英文标题】:Hierarchy vs many tables 【发布时间】:2016-01-19 23:26:55 【问题描述】:我们需要存储位置。有不同类型的位置。区域、街区、建筑物、地板、房间和床位。所以,床在房间里,在地板上等等。
我想我有两个选择。首先是为每种类型准备一个表。还有一个外键来保持它们之间的联系。
或者...
CREATE TABLE [dbo].[Location]
(
[ID] Int IDENTITY(1,1) NOT NULL,
[ParentID] Int NULL,
[LocationTypeID] Int NOT NULL,
[Description] Varchar(100) COLLATE Latin1_General_CI_AS NOT NULL
)
以分层样式保存所有位置的表格。
我喜欢这个想法,就像我们添加新类型一样,它是数据驱动的。没有新表。但是,我认为查询可能很昂贵。
如果我想显示床的详细信息(科学楼4楼5号房间的床1...),它是一个递归函数,它比所有表的简单INNER JOIN获取详细信息更棘手关于一个位置。
一件事。
我需要记录动作。一个运动可能是从一个房间到一个区域。因此,对于单独的表,很难在单个“运动”表中记录运动,因为我要 FK 到哪个表?有了层次结构,这很容易。
此外,报告 1000 人的位置时,会大量调用递归查询以产生结果。慢的?或者有没有一种干净的方法来解决这个问题?
【问题讨论】:
我之前用过这个方法(单表层次结构),一个简单的递归CTE可以辅助快速返回数据 每种方法都有其优缺点... 您还需要确保您的树中不会出现循环。您添加其他位置类型的可能性有多大? 【参考方案1】:所有方法都有各自的优缺点。我见过的另一种方法(尤其是日期)是使用一个表并将层次结构编码在一个字段中(没有父 ID)。
例如 ID(整数列)= 1289674566 表示床 66、楼层 45 等...
当您需要“提取”特定层次结构级别(例如计算不同建筑物的数量)但算术运算非常快并且您可以在基表之上构建视图时,这将需要一些工作希望让最终用户的生活更轻松。
只是另一种选择......
【讨论】:
【参考方案2】:我的固定建议是将数据存储在现实世界中的样子,然后如果幸运的话,您可以查询它而不会受到太大影响。如果点击次数过多,请将数据提取为您可以轻松搜索的格式。
在您的情况下,我会采用您正在考虑的分层样式。这样一来,您就可以拥有一个带有梳妆台的房间的建筑物,带有抽屉的盒子和盒子中的盒子。然后你可以把梳妆台移到另一个房间,所有的东西都随它去。
只要您不试图“欺骗”SQL Server 做某事,您就会发现递归 CTE 的速度很快。
我刚刚在这里回答了一个分层问题,它有一个很好的例子供你参考。特别要注意SORT_PATH。在示例中,我构建了一个如下所示的 SORT_PATH:
TEST01.TEST03.LABSTL
s-s-rS: Recursive Parent Child
您可以在编辑/更新时将此值存储在您的表中,只要您不介意更新记录时的命中,它就可以为您做很多事情(提高性能)。
如果您确实介意更新命中,您可以使用后端进程来保持您的 SORT_PATH 更新。在过去,我使用了一个“DIRTY BIT”字段,当某些内容被修改时会被翻转;然后一个后端进程通过并更新与该记录相关的所有内容,但由于它是一个后端进程,用户不会注意到影响。这对 SEVICE BROKER 来说是一项很好的管理工作——在编辑/更新/删除时设置 DIRTY_BIT=True 并向 SERVICE BROKER 发送一条消息,该消息将启动一个使用 DIRTY_BIT=True 更新任何内容的进程。
【讨论】:
感谢@Robert - 尝试您的示例...但出现转换错误。会继续尝试。 在另一个示例中,ParentKey (COL1) 是一个 VARCHAR,因此连接字符串很容易。您使用的是 INT,因此在构建 DISPLAY_PATH 时需要转换为 VARCHAR。我能够按原样复制答案并让它与 SQL2012 一起运行。您在哪里收到转换错误?【参考方案3】:看看使用 hierachyid 数据类型,它是 SQL Server 原生的 CLR 数据类型,并内置了用于查询父/子类型关系的函数:
Tutorial: Using the hierarchyid Data Type
【讨论】:
以上是关于层次结构与许多表的主要内容,如果未能解决你的问题,请参考以下文章