可更新顺序记录的数据库设计
Posted
技术标签:
【中文标题】可更新顺序记录的数据库设计【英文标题】:Database Design for updatable sequential records 【发布时间】:2012-06-07 15:53:21 【问题描述】:我正在创建一个数据模型来存储与生产跟踪相关的数据。我在一家为客户建模和分析数据的工程公司工作。该过程有几个步骤,并且该过程不断更新。
我正在尝试对流程进行建模并包括父流程和流程的顺序。
例如:
Process Table
---------------------
ProcessID - uniqueidentifier
ProcessName - varchar
ProcessDescription - varchar
...
ProcessOrder Table
---------------------
ProcessID - uniqueidentifier FK - Process
ParentProcessID - uniqueidentifier FK - Process
ProcessOrder - int
...
ProcessOrder
表中的ProcessOrder
列将简单地存储一个数字,表示它代表父进程中的哪个顺序步骤。
例如,一个建模过程有以下步骤:创建新的空模型,命名模型,输入模型参数。 Process
表如下所示:
ProcessID | ProcessName | ProcessDescription
-------------------------------------------------
UUID1 | Modeling | Create Model of Data
UUID2 | New Model | create new empty model
UUID3 | Name Model | name model
UUID4 | Parameters | enter model parameters
ProcessOrder
表如下所示:
ProcessID | ParentProcessID | ProcessOrder
--------------------------------------------------
UUID2 | UUID1 | 1
UUID3 | UUID1 | 2
UUID4 | UUID1 | 3
这种设计的问题是,当工作流更新时,流程顺序会改变,我需要更新 ProcessOrder
记录以用于更改的流程以及具有相同 ParentProcessID
的所有后续记录。
有没有更好的方法来存储这类数据并保持规范化?
【问题讨论】:
【参考方案1】:我认为解决方案类似于我在Advise on database design for a project lifecycle 提出的解决方案
上面的数据是针对前面例子中描述的不同状态值的。因此,对于每个客户项目,您都有以下表格:
a) 客户项目 - Clientid - 对客户端的引用 - 状态(FK 到 ProcessID) - 项目名称、描述、开始日期
b) 状态变化 - 跟踪从一种状态到另一种状态的变化 - 投影 - 旧状态(FK 到 ProcessID) - 新状态(FK 到 ProcessID) - 日期改变 - 注释(以及其他列,如批准等)
【讨论】:
【参考方案2】:这个问题类似于为什么 LinkedLists 具有更好的插入性能(假设您已经有对要插入的节点的引用)与 ArrayList 中的插入相比。
在 ArrayList 中进行插入时,您必须移动所有记录以为新插入腾出空间。假设有 N 条记录,这可能需要 O(N) 时间(想象在列表的开头插入)。
在 LinkedList 中,您只需更新要插入的点处的节点。根据上述假设,这将花费 O(1) 时间,因为您只需要更新 Prev 节点和 Next 节点。
要在数据库中设置 LinkedList 结构,而不是 ProcessOrder 列,您将有两列,PrevProcessID 和 NextProcessID。
选择此选项时出现问题。天真的方法是在表上递归地自连接。这将导致 N 个连接。
不要使用 N 个连接,而是不要使用任何连接并选择所有具有父 ID 的进程。
在代码中,有一个包含以下字段的 Process 对象: 父进程 ID 进程ID 上一个进程ID 下一个进程ID
在从选择中读取记录时,创建这些对象并将它们存储在以 ProcessID 作为键的 HashTable 中。这将花费 O(N) 时间来遍历 select 语句。
现在记录在 HashTable 中,您可以通过查找表中的 NextProcessID(或 PrevProcessID)轻松地从一个节点移动到下一个节点。使用 HashTable 可以让您免于进行 N 次连接,而是花费 O(N) 时间来设置。
比较两种方法
1) 您现在拥有的当前解决方案。这是一个 ArrayList 类型的解决方案(将 ProcessOrder 视为索引)。插入需要 O(N) 时间,而您可以节省读取时间,因为您不必设置 HashTable。但是,如果您已经循环通过返回的记录来设置实体对象,那么这将是 LinkedList 解决方案中相同的设置时间。
2) 我提出的解决方案。这是一个 LinkedList 类型的解决方案。假设您知道要插入的位置,插入需要 O(1) 时间。设置时间需要 O(N) 时间。
【讨论】:
以上是关于可更新顺序记录的数据库设计的主要内容,如果未能解决你的问题,请参考以下文章