我应该如何在MS SQL共享服务器环境中对我的数据进行版本设置


How should I version my data in an MS SQL shared server environment?

服务器是带有Hostgator的共享Windows托管服务器。我们被允许"无限"的MS SQL数据库,每个数据库都被允许"无限制"的空间。我正在用PHP编写网站。数据(不是数据库模式,而是数据)需要进行版本控制,以便(理想情况下)我的客户在登录网站时可以从选择框中选择他想要的数据库版本,然后(大约每月一次)标记当前数据,也可以通过网站上的一个简单表单。我已经想出了几种理论方法来做到这一点,但我对其中任何一种都不感到兴奋。

1) 在每个表上放一个VersionNumber列;有一个主版本表,列出登录时选择框的所有版本。当被标记时,数据库中每个表中没有版本号的每一行都将被复制,并且原始表将被赋予版本号。

这对我和我的客户来说似乎是最简单的想法,但我担心数据库在几个月内会非常慢,因为每个表每个月都会增长(至少)其原始大小。在任何一个版本中都没有太多的数据,而且可能永远不会有。但在同一张表中相乘的版本让我害怕

2) 每次标记时都复制数据库。

由于服务器是共享的,所以这似乎必须由我的客户端手动完成,所以我已经不喜欢这个想法了。但除此之外,旧的数据库必须能够使用当前的网站代码,并且随着时间的推移(这是不可避免的)数据库结构的变化,旧的DB将不再使用新的网站代码。

3) 每次标记时,在同一个数据库中创建重复的表(名称中包含版本)。比如[v27_Employee]。

与想法(1)相比,这里的好处是没有一个表的大小会变得巨大,从而允许查询保持速度。与想法(2)相比,理论上可以通过简单的网站标签表单轻松完成,而不是由我的客户手动完成。问题是,当我试图解释哪个Employee表与哪个Address表连接时,我的PHP代码中的查询会变得一团糟,这取决于所选的版本,因为它们都有相同的名称,但不同;而且,随着代码的更改,旧的DB表不再匹配,问题与(2)相同。

最后,有人有什么好的建议吗?最佳实践?他们过去做过的有效的事情?

谢谢大家。

选项1是最明显的解决方案,因为它的维护开销最低,而且最容易使用:只需在查询中添加@VersionNumber,就可以随时查看任何版本。如果您希望或需要,这意味着您还可以通过为每个版本号而不是实际表创建视图来同时实现选项3。如果应用程序一次只查询一个版本,请考虑将VersionNumber设置为集群主键的第一列,以便一个版本的所有数据都物理存储在一起。

而且目前还不清楚你有多少数据。你说"不是很多",但这毫无意义。如果你真的有很多数据(比如说,分成数亿行),如果你有Enterprise Edition(你没有说你使用的是哪个版本),你可以使用表分区来"拆分"非常大的表,以获得更好的性能。

我的结论是现在就做最简单、最容易维护的事情。如果效果良好,那么你就完了。如果没有,你至少可以从一个简单、稳定的起点重新设计你的设计。如果你现在做一些更复杂的事情,如果你需要重新设计它,你将有更多的工作要做。

你可以每月将可版本控制的表复制到一个新的数据库中。如果需要在可版本控制的表和不可版本控制表之间进行联接,则需要进行跨架构联接,这在SQL Server中是受支持的。这种方法比在单个模式中复制表要干净一些,因为您的数据库资源管理器将开始难以处理所有旧表。

我最终要做的是为每个版本创建一个新的模式,并在每次对DB进行版本控制时复制表、触发器和键。例如,我有一张表:

[dbo].[TableWithData]

我把它复制到同一个数据库中的这个表中:

[v1].[TableWithData]

然后,当用户想要查看旧表时,他们会选择哪个版本,我的代码会自动将每个查询中的每个[dbo]实例更改为[v1]。它在概念上相当简单,用户不必对版本做任何复杂的事情——只需在表单中键入"v1",然后点击提交按钮。我的PHP和SQL完成了剩下的工作。

我确实发现有些表必须保持独立——我制作了一个名为[ctrl]的不同模式,将不会进行版本控制的表放入其中,例如用户名/密码表。这样,我只复制[dbo]表。

它已经运行了一年左右,目前似乎运行良好。到目前为止,他们只发布了4次版本。我唯一一直无法解决的问题是,触发因素似乎不知何故丢失了。这可能是我非常复杂的PHP的问题,而不是DB版本控制概念本身的问题。