2

一位同事最近向我描述了重新构建数据库的计划。新数据库将符合简单的星型模式:父表将包含一个键和一些上下文信息,该键将用作其他表中的外键字段。外键字段可能多次出现在同一个子表中。

伪代码:

TABLE Parent
   INT key PRIMARY_KEY
   INT foo
   ...

TABLE Child1
   INT key FOREIGN_KEY REFERENCES Parent.key
   BLOB bar
   ...

TABLE Child2
   INT key FOREIGN_KEY REFERENCES Parent.key 
   VARCHAR tar
   ...

设计背后的动机是简化 和 之间的 JOIN ParentChild<n>这在以前的模式中很复杂。

为了进一步加快 JOIN,我的同事希望尽量减少 OUTER JOIN 的使用。具体来说,她想通过使用 JOINS 并通过以特定方式维护子表中的数据来模拟 OUTER JOIN:填充所有子表,以便对于每个keyin Parent,至少有一行 inChild<n>具有该key值,即使该行否则充满nulls。这样,在ParentChild<n>on之间执行的任何 JOIN 都会为每个inkey返回至少一个结果,更像是 OUTER JOIN。keyParent

撇开以这种方式维护数据是否值得付出努力的问题不谈,假设所有key字段都已正确索引并且大约一半的子行被null淘汰,这种方法是否比执行 OUTER JOINS 更高效?

这个问题似乎可以归结为“对索引中存在的值而不是不存在的值进行索引查找更快?” 假设索引像 B 树或散列一样运行,我的答案是“否”,但我知道的不够多,无法确定。

4

2 回答 2

2

就个人而言,我没有注意到外连接和内连接之间的主要性能差异。为什么你的同事认为他们比较慢?

添加额外的记录对性能有两个影响。原始数据变大,需要更多的页面来存储数据。这会对性能产生很大的影响,特别是如果额外的页面(没有有用的数据)正在与更有用的结构(比如索引)竞争空间。

第二个影响是对指数的影响。它需要更大,这可能会导致更深的索引和更多的索引页面。这两者都会对性能产生影响。

还有另一个问题,与性能无关。编写查询的用户/开发人员需要充分了解这些空记录的存在。执行 COUNT(*) 或 COUNT() 并期望结果准确反映包含数据的记录数非常容易。如果不是这种情况,您可能会在未来导致编码问题。

于 2012-09-12T22:05:41.950 回答
1

我认为这种方法不会提高性能。

内连接通常比外连接快。这是因为内部连接的限制性更强,使优化器有更多机会在计划的早期减少结果集。

但是,如果您人为地添加数据,您的内部连接将不再受到更多限制。

于 2012-09-13T07:15:57.810 回答