可更新顺序记录的数据库设计

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) 时间。

【讨论】:

以上是关于可更新顺序记录的数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

程序猿修仙之路--数据结构之设计高性能访客记录系统

创建唯一索引的 sql语句

SQLIte如何设置自动增长的字段?

[游戏更新]游戏更新框架的设计

杨玲 徐思 《面向对象程序设计(java)》第十一周学习总结

MySQL索引设计