首先(出于好奇)当前模式如何指示当前版本是什么?您是否只有多个具有相同 DocumentTitle 的“WikiDocument”条目?
我也不清楚为什么您需要版本级别的“LastActivity”。我看不出“LastActivity”如何与“版本”的概念相适应——在大多数wiki 中,“版本”是一次性写入的:如果你修改了一个版本,那么你就是在创建一个新版本,所以版本上最后更新类型值的概念是没有意义的——它实际上只是“创建日期”。
确实,您设计的“自然”模式是#2。就个人而言,我有点喜欢旧的 DB 公理“规范化直到它受伤,然后非规范化直到它起作用”。#2 是一个更干净、更好的设计(简单,没有重复),如果你没有紧急的理由去规范化到版本 3,我不会打扰。
最终,归结为:您是否担心“性能更高”的设计是因为您观察到了性能问题,还是因为您假设可能有一些问题?没有真正的理由#2 不应该表现良好。分组在 SQL Server 中不一定是坏消息——事实上,如果查询有适当的覆盖索引,它可以执行得非常好,因为它可以导航到索引中的特定级别以查找分组值,然后使用索引的其余列用于 MIN/MAX/whatever。按 NVARCHAR 分组并不是特别糟糕——如果没有观察到它是一个问题,请不要担心,尽管(非二进制)排序规则可能会让它有点棘手——但在版本 2 中,你需要GROUP BY 你可以通过 WikiHeadId 来做,对吧?
如果您在当前版本上执行大量操作(我假设您会这样做),那么可以让生活变得更轻松的一件事是,将 FK 从头表添加回主体表,指示当前版本。如果您想查看点击次数最多的当前版本,现在的 #2 可能是:
SELECT TOP ...
FROM WikiHead
INNER JOIN
(SELECT WikiHeadId, MAX(WikiBodyVersion) /* or LastUpdated? */ AS Latest
FROM WikiBody GROUP BY WikiHeadId) AS LatestVersions
INNER JOIN WikiBody ON
(Latest.WikiHeadId = WikiBody.WikiHeadId)
AND (WikiBody.WikiBodyVersion = LatestVersions.Latest)
ORDER BY
Views DESC
或者
...
INNER JOIN WikiBody ON
(WikiHead.WikiHeadId = WikiBody.WikiHeadId)
AND (WikiBody.WikiBodyVersion =
(SELECT MAX(WikiBodyVersion) FROM WikiBody WHERE WikiBody.WikiHeadId = WikiHead.WikiHeadId)
...
两者都很恶心。如果 WikiHead 保留一个指向当前版本的指针,它只是
...
INNER JOIN WikiBody ON
(WikiHead.WikiHeadId = WikiBody.WikiHeadId)
AND (WikiHead.Latest = WikiBody.WikiBodyVersion)
...
或者其他什么,这可能是一个有用的非规范化,因为它让你的生活更轻松,而不是为了性能。