在MySQL中设计父子关系

时间:2018-04-23 16:17:35

标签: mysql sql database database-design data-modeling

需要输入数据模型设计

parent_table

id (PK)
current_version
latest_child_id

child_table

id (PK)
parent_table_id (FK to parent)
version (running number . largest number implies latest child record)

parent_table与child_table之间的关系为1:m。 另外,parent_table保留一个指向子表中记录的最新版本的指针。

系统会将n个可变行插入child_table并更新parent_table以指向最新版本 - 以便更快地读取。

我的问题是:

  1. 让parent_table存储最新是不好的做法 子表的版本?
  2. 我在看潜在的表现     问题\锁定问题?因为任何插入孩子 table-还需要在父表上锁定吗?
  3. 有问题的数据库: MySQL

3 个答案:

答案 0 :(得分:2)

让parent_table存储最新版本的子表是不好的做法吗?

像“不良习惯”这样的短语会加载上下文。我更倾向于考虑权衡,并理解该级别的决策。 通过存储您可以另外计算的属性,您正在进行denormalization。这是处理性能挑战的既定方法 - 但它只是其中之一。权衡取舍大致如下。

  • 否定:占用更多存储空间。假设这没关系
  • 否定:需要更多代码。更多代码意味着更多的机会出现错误。考虑将数据访问代码包装在测试套件中。
  • 否定:非规范化模式可能需要额外的“大脑空间” - 您必须记住您计算(例如)父项具有的子项数,但通过查看父表中的属性来查找最新项。在理想的世界中,规范化模式描述了业务上下文,而不必记住实现细节。
  • 否定:可能会使您的数据模型在未来更难扩展。随着您添加更多实体和属性,此非规范化表可能变得越来越难以保持同步。一个非规范化列通常很容易使用,但是如果你有很多非规范化列,那么保持它们都是最新的可能非常困难。
  • 否定:对于不经常访问的数据,非规范化设计可能比动态计算更具性能。你的问题2就是一个例子。在复杂的场景中,多个线程可能会在非规范化数据中产生不一致。
  • 正面:对于经常读取的数据,以及计算成本高昂的地方,非规范化架构将允许更快的读取访问。

在您的情况下,我怀疑您需要将此数据存储为非规范化属性。通过在parent_table_id, version DESC上创建索引,即时检索此数据的速度太快(假设您的数据库拥有数百万条记录,而不是数十亿条记录)。

一般情况下,我建议只在以下情况下进行非规范化:

  • 你可以证明你有性能问题(即你已经测量过了)
  • 您无法通过创建更好的索引来提高绩效
  • 您无法通过更好的硬件提高性能

我是否在研究潜在的性能问题\锁定问题?因为任何插入子表 - 也需要在父表上锁定?

正如@TheImpaler所写,可能没有。但是,它取决于插入逻辑的复杂性(它是否会执行任何可能减慢速度的复杂计算?),以及几个并发线程尝试更新父记录的可能性。在这些情况下,您可能还会得到不一致的数据。

答案 1 :(得分:2)

ORDER BY child_id DESC LIMIT 1

是一种非常有效的方式来获得最新的"孩子(假设你有INDEX(child_id))。

这消除了对顽皮"多余"的需要。你提出的信息。

答案 2 :(得分:1)

  
      
  1. 让parent_table存储子表的最新版本是不好的做法吗?
  2.   

不,如果它符合您的应用要求,那就完全没问题。您需要添加额外的逻辑来正确更新表,但就是这样。数据库为您提供了一系列存储数据和关系的可能性,这是一个非常好的选择。

  
      
  1. 我是否在研究潜在的性能问题\锁定问题?因为任何插入子表 - 也需要在父表上锁定?
  2.   

这取决于您更新/插入/删除孩子的频率。考虑到当前的数据库服务器,除非变化率超过每秒200+,否则很可能不会出现问题。独占锁定可能成为大量交易的问题。

通常锁会在行级别。它,它们将仅锁定您正在使用的行,因此具有不同父项的多个线程不会产生瓶颈。

如果您的系统确实需要高级别的交易(1000+ /秒),那么我看到的选项是:

  • 投入更多硬件:最简单的方法。只需买一台更大的机器,问题就解决了......至少有一段时间,直到你的系统再次增长。
  • 使用乐观锁定:此策略根本不需要您执行任何实际锁定。但是,您需要添加一个额外的数字列来存储行的版本号。
  • 切换到另一个数据库:MySQL可能无法很好地处理真正的高音量。如果是这种情况,您可以考虑使用PostgreSQL,甚至是Oracle数据库,它确实具有更好的缓存技术,但也非常昂贵。