在关系数据库中实现高效的外键

时间:2015-05-04 14:53:19

标签: mysql sql-server postgresql

我所知道的所有流行的SQL数据库都通过索引来有效地实现外键。

假设N:1关系学生 - >学校,学校ID存储在学生表中,带有(有时是可选的)索引。对于一个特定的学生,你可以找到他们的学校只是查找该行中的学校ID,对于一个特定的学校,你可以通过在学生的外键中查找索引中的学校ID来找到它的学生。关系数据库101。

但这是唯一明智的实施吗?想象一下,您是数据库实现者,而不是在外键列上使用btree索引,而是在关系的另一(多)端的行上添加(对用户不可见)集。因此,不是在学生中索引学校ID列,而是有一个不可见的列,它是学校行本身的一组学生ID。然后,为特定学校提取学生是一个简单的迭代集。这种实施是不常见的原因吗?是否存在一些无法以这种方式有效支持的查询?这两种方法似乎或多或少等同,以特定的实现细节为模。在我看来,你可以模仿另一个解决方案。

在我看来,它在概念上与分裂btree相同,后者包含(school_id,student_row_id)的排序运行,并将每次运行存储在学校行本身。在学校主键中查找学校ID可以为您提供学生ID,就像查找外键索引中的学校ID一样。

为清晰起见,

已修改

2 个答案:

答案 0 :(得分:3)

您似乎建议将“逗号分隔的值列表”存储为表格的字符列中的字符串。而且你说它“就像迭代集合一样简单”。

但是在关系数据库中,当它作为列中的值列表存储时,“迭代集合”并不简单。也没有效率。它也不符合关系模型。

考虑将成员添加到集合或从集合中删除,或者甚至仅确定成员是否在集合中时所需的操作。考虑强制执行完整性所需的操作,以验证该“逗号分隔列表”中的每个成员是否有效。关系数据库引擎不会帮助我们解决这个问题,我们必须自己编写所有代码。

乍一看,这个想法似乎是一个很好的方法。而且完全有可能做到,并使一些代码工作。但是,一旦我们超越了琐碎的示范,进入真实问题和现实世界数据量的领域,事实证明这是一个非常非常糟糕的想法。

存储逗号分隔列表是非常熟悉的SQL反模式。

我强烈推荐Bill Karwin的优秀书籍第2章:SQL Antipatterns: Avoiding the Pitfalls of Database Programming ISBN-13:978-1934356555

(这里的讨论涉及“关系数据库”以及它是如何设计的,遵循关系模型,由Ted Codd和Chris Date开发的理论。)

“所有非密钥列都依赖于密钥,整个密钥,除了密钥之外什么都没有。所以请帮助我Codd。”

问:这种实施是不是很常见?

是的,这种情况并不常见,因为它面对关系理论。它使一个简单的问题(对于关系模型)成为一个混乱的混乱,关系数据库无法帮助我们。如果我们存储的只是一串字符,并且数据库永远不需要对它做任何事情,除了存储字符串并检索字符串之外,我们会很好。但我们不能要求数据库将其解释为代表实体之间的关系。

问:是否存在一些无法以这种方式有效支持的查询?

任何需要将“值列表”转换为要返回的行集的查询都是低效的。任何需要识别包含特定值的“值列表”的查询都是低效的。从“值列表”中插入或删除值的操作效率很低。

答案 1 :(得分:2)

这可能会在一小部分情况下为您带来一些小的好处。但缺点很多。

  1. 此类索引不仅可用于父记录的直接连接。查询可能GROUP BY FK列,或者将其加入临时表/子查询/ CTE;所有这些情况都可能受益于索引的存在,但没有一个查询涉及父表。
  2. 即使是来自父级的直接连接也经常涉及对子表的附加约束。因此,在子表上定义的索引通常包括除密钥本身之外的其他字段。
  3. 即使此算法中涉及的步骤似乎较少,但这并不一定等同于更好的性能。数据库不能一次从磁盘读取一列;它们通常以固定大小的块加载数据。因此,将这些信息存储在一个连续的结构中可能会比在多个元组中分散信息更有效地访问它。
  4. 我所知道的数据库不能内联任意大的列;要么你有几千个孩子的硬限制,要么你必须把这个列表推到一些外线存储(并且有这个额外的间接水平,你可能已经失去了索引查找的任何好处。
  5. 数据库不是为列值的部分读取或就地编辑而设计的。无论何时访问它,您都需要获取整个列表,更重要的是,只要它被修改就替换整个列表。
  6. 事实上,只要子列表发生变化,您就需要复制整个; MVCC model通过维护记录的多个版本来处理并发修改。您不仅会生成更多版本的记录,而且每个版本都拥有自己的子列表副本。
  7. 可能大多数诅咒的事实是子表上的插入现在触发了父表的更新。这涉及锁定父记录,这意味着不再允许并发子插入或删除。
  8. 我可以继续。在许多这些案例中可能存在缓解因素或明显的解决方案(更不用说我本身的直接误解),尽管我可能忽略了许多问题。无论如何,我很满意他们已经很好地想到了这一点......