用于索引的冗余DB列

时间:2014-04-01 13:22:42

标签: database database-design

我定义了一些数据库表,大致如下所示:

DB

为了快速运行查询,按时间顺序检索Person MailMessages,无论发送的MailAccount是什么,我都想要一个索引对于MailMessage表,按(PersonId,ReceivedTime)排序。这意味着将一个冗余的PersonId列添加到MailMessage表中,如下所示:

DB

......或者是吗?这样做有什么更简洁的方法吗?如果不是,最好的做法是将PersonId作为MailMessage表中的外键,或者不应该这样做,因为它在概念上不是外键,而只是用于(PersonId,ReceivedTime)索引的列?

2 个答案:

答案 0 :(得分:2)

您正在做的事情称为denormalization。对这个概念的利弊进行全面讨论对于SO来说有点多了。

使用Materialized View(在SQL Server中称为索引视图)也可以进行此类优化。

答案 1 :(得分:2)

是的,你可以这样做,但需要在MailAccount上的表{MailAccountId, PersonId}中使用密钥,因此表MailMessage中的FK可以引用它。从强制执行唯一性的角度来看,这是多余的,因为仅{MailAccountId}已经是唯一的。

还有另一种方法:使用识别关系和自然键。例如:

enter image description here

这实现了基本相同的目标,但每个表只有一个键(和底层索引)。

请注意底部表格中PK字段的顺序:它允许查询...

SELECT *
FROM MailMessage
WHERE PersonId = ?
ORDER BY ReceivedTime

...通过主索引上的索引范围扫描得到满足。如果表恰好是clustered,那么DBMS甚至不必在那之后访问表堆(根本没有表堆 - 行直接存储在B-Tree中)。

在不使用冗余密钥(这也适用于群集)的情况下避免JOIN是自然密钥与代理密钥的优点之一。你可以想象,list of pros and cons并没有结束。