Rac*_*hel 5 database-design sql-server
我们有一个表,只存储一个AccountId, TagId, 和DateCreated。用户可以更新帐户上的标签,从而在此表中添加或删除记录。一个帐户上不能存在多个标签,但可以多次添加和删除相同的标签。此表主要用于用户构建的查询中,以使用标签表JOIN或EXISTS标签表过滤帐户。
我被要求开始记录标签历史记录,我正在尝试决定使用现有表上的IsDeleted和/或DateDeleted列是否更好,或者我是否应该创建一个单独的历史记录表来存储这些数据。
跟踪历史记录的主要目的是在特定时间点运行报告。例如,获取 2013 年 1 月期间带有 TagA 的帐户的数据。
在尝试在两者之间做出决定时,我应该考虑哪些因素?
问题IsDeleted在于它的低基数:0 或 1。这使得它不可索引,并且由于您的所有查询都会添加IsDeleted = 0到 WHERE(或 JOIN)条件中,这种明显的微不足道的变化使很多事情变得复杂。您覆盖索引将突然需要查找基表以确定该行是否合格。有一些措施可以改善行为,但必须正确考虑并一致部署(请注意,其中一些缓解措施是相互排斥的,请单独评估):
IsDeleted作为聚集索引中最左边的键。这有效地将集群表“拆分”为两个区域(“已删除”和“活动”)。它还强制IsDeleted在每个非聚集索引中事实上列,从而避免需要查找值。IsDeleted在每个非聚集索引中作为最左边的键添加。可能听起来很极端,但如果所有查询都IsDeleted在 WHERE 中指定,则可能非常有效。IsDeleted作为包含列添加到每个非聚集索引。与上面的选项不同,这不会改变现有索引的查找/范围/查找语义,而是使IsDeleted检查过滤在每个访问路径中可用。特别是IsDeleted = 1在很少发生的情况下会非常有效。IsDeleted = 0. 可能对大型表有效,但有点危险,因为过滤的索引对于对已删除行感兴趣的查询变得不可用。从引擎的角度来看,一个单独的历史表可以更清晰地切割:是一个不同的表,没有混乱/风险的计划选择来应对。但它对应用程序的影响更大。如果查找行的历史记录是例外,应用程序更改是合理容易的,那么我会首先考虑这个选项,因为它具有(严重)性能回归的风险最小。
我强烈建议不要使用混合解决方案(例如,tags 和 tags_history 表以及将它们联合起来的视图),这样的解决方案具有上述所有缺点而没有任何优势。一般来说,任何声称“影响最小”或“透明变化”的东西都是蛇油。根据定义,这(添加应用程序层行版本控制/行历史记录)是一个影响很大的更改,它将在应用程序中产生很大的影响。
| 归档时间: |
|
| 查看次数: |
2193 次 |
| 最近记录: |