一位同事最近向我描述了重建数据库的计划。新数据库将符合简单的star schema:父表将包含密钥和一些上下文信息,该密钥将用作其他表中的外键字段。外键字段可能多次出现在同一子表中。
伪代码:
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
...
设计背后的动机是简化Parent
和Child<n>
之间的JOIN,这与之前的架构相比很复杂。
为了进一步加快JOIN,我的同事希望尽量减少使用OUTER JOIN。具体来说,她希望通过使用JOINS并以特定方式维护子表中的数据来模拟OUTER JOIN:填充所有这些,以便key
中的每个Parent
至少有一个Child<n>
在key
中使用null
值的行,即使该行已满Parent
秒。这样,在Child<n>
上的key
和key
之间执行的任何JOIN都会为Parent
中的每个key
返回至少一个结果,更像是一个OUTER JOIN。 / p>
抛开以这种方式维护数据是否值得努力的问题,假设所有null
字段都被正确编入索引并且大约有一半的子行,则这种方法比执行OUTER JOINS更有效。被{{1}}排除了吗?
问题似乎归结为“对索引中存在的值而不是不存在的值进行索引查找会更快吗?”假设索引的操作类似于B树或哈希,答案就像“不”,但我不知道是否足够确定。
答案 0 :(得分:2)
就个人而言,我没有注意到外连接和内连接之间的主要性能差异。为什么你的同事认为他们比较慢?
添加其他记录会对性能产生两种影响。原始数据变大,需要更多页面来存储数据。这会对性能产生很大影响,特别是如果其他页面(没有有用数据)与更有用的结构竞争空间(比如索引)。
第二个影响是指数。它需要更大,这可能会导致更深的索引和更多的索引页。这两者都会对性能产生影响。
还有另一个问题,与性能无关。编写查询的用户/开发人员需要完全理解存在这些空记录。执行COUNT(*)或COUNT()非常容易,并期望结果准确反映包含数据的记录数。如果不是这种情况,可能会导致编码问题。
答案 1 :(得分:1)
我认为这种方法不会提高性能。
内部联接 通常比外部联接更快。这是因为内部联接更具限制性,为优化器提供了更多机会来减少计划中早期的结果集。
但是如果你人为地添加数据,你的内部联接就不再具有更多的限制性了。