SQL Server数据库设计用于“已存档但可用”的数据


12

我们有一个打算“缩小”的大型数据库(> 1TB)。数据库围绕一个主要实体,我们称其为“访问”。为了讨论起见,假设它是医学实践的数据库。

总共有30种访问“类型”,例如程序,年度,随访,免疫等,每种类型都是“访问”的辅助表,例如“ visit_immuno”。

自2000年以来,该数据库已积累了大约12年的数据。有人建议我们在“实时”版本中保留大约3年的数据,而其余数据则保留在“ old_data”数据库中。由于日期已标准化,因此仅存储在“访问”表中。Visit表还包含一个ROWVERSION列和一个BIGINT伪身份(聚集)列。出于所有目的和目的,假设群集密钥由SEQUENCE(SQL Server 2012 Enterprise)填充-我们将其命名为cid

visit.date当医生的推移延长探视,并与他的数据的“公文包”的回报并不总是以相同的顺序作为聚集键,例如,它被合并到主表。“访问”表也进行了一些更新,这将导致该ROWVERSION列与ciddate列不同步-简单地说,由于这个原因,它们都ROWVERSION不会cid创建合适的分区键。

从“活动”中删除数据的业务规则是,visit.date必须大于36个月并且visit_payment必须存在子记录。另外,“ OLD_DATA”数据库不包含任何基本表visit%

因此,我们最终得到:

直播DB(日常使用) -所有表老数据DB -对于较旧的数据visit%

该提案要求使用组合DB,该组合DB是一个外壳,其中包含(除外)中所有基本表的同义词以及两个数据库中所有表的UNION ALL的视图Live DBvisit%visit%

假设在Old-Data数据库中创建了相同的索引,查询在UNION-ALL 视图上的性能是否良好?哪种类型的查询模式可能会使UNION-ALL 视图的执行计划失败?


3
a)归档旧数据和b)保持可访问性的动机是什么?维护费用?性能问题?归档数据是否需要应用程序无缝访问?是否对应用程序进行了修改?
Mark Storey-Smith

(a)保持主数据库较小。它被复制到其他3个环境-开发,预测试,测试。还有复制的镜像和备份,所有这些都由昂贵的存储支持。(b)由于下游系统当前可以访问所有数据,因此可以维持现状。(c)该应用程序的实例可以针对具有所有视图的“组合”数据库运行,但我怀疑它可能根本无法执行。
孔夫子2013年

为了澄清起见,归档数据仍然是可读写的,对吗?还是只读的?
乔恩·塞格尔

旧数据将更改为只读和100%填充的页面。如果有人尝试对旧数据进行愚蠢的操作,则连接到组合视图的应用程序实例可能会引发错误-我们不在乎。
孔夫子2013年

认为用于历史数据和部分备份/还原的只读文件组可以解决此问题,而无需添加Shell数据库和同义词。我说,因为我已经一段时间没有干预它的机制了,需要刷新我的记忆。不知道它如何适合复制,但是我想问一下为什么要将实时数据库复制到下游环境。
Mark Storey-Smith

Answers:


4

为了方便起见,假设调用了实时数据库,而调用LiveDb了主动数据库ArchiveDb

  • 添加一个UNION ALL视图以通过同义词LiveDb指向ArchiveDb数据库中的表(无需使用同义词进行合并的db)
  • 启用“分区”,visit.date然后将该列visit_payments也进行非规范化(如果尚未存在的话)(这提高了同一位置的联接性能)
  • 仅在可能的情况下才归档两个大表(减少触发优化器的机会)。保留UNION ALL视图和其他表,LiveDb以便将所有较小表的联接保持在本地
  • 添加在两个表CHECK约束LiveDbArchiveDb 描述的范围visit.date包含在表中。这有助于优化程序从包含该列的搜索和扫描中消除存档表visit.data。您将必须定期更新此约束。
  • 在UNION ALL视图中,添加过滤条件为的WHERE条件visit.data。这是您已经在检查约束中提供的提示的补充。这最大程度地降低了过滤器被推下的机会
  • 如果您有EE,请在存档数据库中对表进行分区(但不要在实时数据库中)。如果您真的想花哨的话,请使用归档数据库的文件组级别备份/还原来节省备份时间。
  • AchiveDb如果尚未考虑,请考虑使其进入SIMPLE恢复模式。您不太可能需要以下内容的事务日志备份ArchiveDb
  • 当在LiveDb和之间移动数据时,使用INSERT ... WITH(TABLOCK)SELECT ... WITH(ROWLOCK)强制最小化目标上的日志记录 ArchiveDb

以上所有内容都不能保证优化程序会从搜索和扫描中消除存档表,但这样做的可能性更大。

当消除没有发生时。这些是您可能会看到的效果(此列表可能不完整)。对于搜索,您将在每个查询上获得一个额外的搜索(这会提高IOPS)。对于扫描,结果可能对性能造成灾难性的影响,因为您最终可能同时扫描存档表和活动表。以下是使优化器跳闸的典型方法:

  • 如果您将visit%表联接在一起,并且不visit.data将联接条件包括在表中(这就是为什么要进行非规范化的原因)。因此,您可能希望修改某些查询
  • 如果在visit.data另一个表之间(例如,日期维度)进行散列联接,则可能无法正确消除表
  • 如果您尝试汇总归档表中的数据
  • 如果您对任何内容进行过滤visit.data,例如,则直接在视图键上进行搜索。

对于最后一种情况,可以通过在cid- 上添加另一个检查约束来保护自己免受最坏的影响。您确实提到过,cid表中行的日期和进度不是“干净” 的顺序。但是,您是否可以维护一个包含以下信息的表:“ cid由于这个数字visit.data或类似数字,因此没有其他数字?” 然后,这可能会导致其他约束。

要注意的另一件事是,一旦查询分区视图,并行查询可能会产生更多的线程(因为两个“子表”都将面临相同的并行优化)。因此,您可能希望限制服务器或并行查询上的MAXDOP。

顺便说一句,如果您非常了解查询-您甚至可能不需要在两个数据库中使用相同的索引(这是假设您100%确信可以正确消除表)。您甚至可以考虑将列存储用于ArchiveDb


-1

我们要做的方法是将旧数据成批写入新创建的数据库,然后从活动数据库中删除旧数据。这样,两个数据库都可以访问。您还可以备份新创建的数据库并将其还原到其他位置,以消除生产服务器中的大量内存。希望这是可以满足您需求的解决方案。


OP需要走得更远,以保持应用程序兼容性。你读过这个问题吗?
乔恩·塞格尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.