淘汰过时的数据库列的最佳实践是什么?[关闭]


14

我正在设计一个应用程序,它将在早期阶段从客户端收集数据A,B和C,但稍后将收集数据A,B和D。

A,B,C和D非常相关,现在作为单个数据库PostgreSQL表T的列存在。

一旦不再需要C,我想从我的应用程序中删除它的引用(我使用Django ORM),但是我想保留已经输入的数据。最好的方法是什么?

我曾考虑过为ABD创建一个新表,但这意味着可能会导致引用表T的任何行出现问题。

我可以只保留C列,并删除代码中对它的引用,以使现有数据得以保留。

有没有我看不到的更好的选择?

一些额外的细节:

行数不会很大,很可能每个用户1-2行。这是一个大众市场应用程序,但是当我从C切换到D时,用户群还不会很大。尽管有可能,但C和D可能不会同时收集。C和D可能分别代表多个列,而不仅仅是每个列。


我认为解决此问题的正确方法取决于您是否需要区分从{A,B,C}收集的行和从{A,B,D}收集的行,如果是,如果当前数据模型允许这样做。而且,这还取决于您对从{A,B,C}收集的行的处理方式-新版本的应用程序将其显示为{A,B,D},其中包含一个空的“ D”,但用户看不到C列的内容,可能会试图从数据库中删除该行(如果应用程序允许删除行),因为他看不到该内容。
布朗


有没有同时收集过C和D的行?还是总是A,B,C,Null或A,B,Null,D?如果您在短时间内在同一行上有C,D ...为什么没有A,B,C和A,B,D表呢?我们在说...数百行数据吗?百万?数十亿?响应时间是一个因素吗?许多细节使每种情况都各不相同...
WernerCD '18

@WernerCD在问题中添加了有关我的案例的一些详细信息
Jad S

您可以使用列,也可以不使用。使用它,保留它。不要放下它。如果要保留数据,请将其移动到其他表(无外键约束)或导出。
Thaylon

Answers:


31

如果您想保留数据,那么它不是过时的。只需将其保留在原处即可。如果某些映射到表的类没有映射每列,那就很好。


1
一段时间后,您可能会得到很多空列
Ewan

8
也许他们可以要求在stackexchange上采取最佳实践方法。...发生这种情况时
Ewan,

8
我想我对这种答案的不满是,确保您可以摆脱它,但它的技术债务很高。最终,你想要一个真正的解决方案,不用解释了所有的新员工,为什么你现在科技巨头同类最佳公司拥有的arent二手散通过你的数据库随机列
伊万

1
我明白了@Ewan的观点,但是对于我的用例来说,应该可以做到。事情可能在我的脑海中被简化了,但是如果需要的话,稍后运行数据迁移脚本应该很简单,如果需要,可以参考T表中的原始行将C数据复制到新表中,然后删除T表中的C列。
Jad S

3
@Ewan-假设列过时不会发生一次-随着发现或更改设计需求,它可能会发生多次。如果将null列的替代方法是在列过时的任何时候拆分成单独的表(例如,继承结构),则数据库将被废弃表的联接表所取代。我相信这很有可能会变得更糟。
Thomas W

8

好的,因此您的情况是希望旧行具有属性C,而新行则不具有。

这等效于具有类继承关系

class All
{
    string A;
    string B;
}

class Old : All
{
    string C;
}

class New : All
{
    string D;
}

您将在数据库中使用具有1对1关系的三个表来表示

table All
    id varchar
    A varchar
    B varchar

table Old
    id varchar
    C  varchar

table New
    id varchar
    D  varchar

因此,您可以创建一个迁移脚本来创建新的旧表,将id和C数据复制到其中,然后从“全部”表中删除C列。

根据需要使用新的sql更新代码;

或者,如果您只需要查询旧的C数据,则可以用A,B,C创建一个新的Archive表,然后复制所有数据并删除C列,然后将D col添加到“ Live”表中


1
如果我拆分表格,则希望其中三个使用:{A,B} {C} {D}
空加瓜

与示例不符?
伊万

等待。我很想念
Ewan

2

如果可能要考虑数据存储,则拆分表:键/ A / B键/ C键/ D

您可以通过视图(在db中定义数据位置)或通过更改ORM定义来执行访问。

这不是性能最高的(涉及连接),但是随着时间的推移,它可以呈现A / B / C / D的任何组合,而无需更改底层存储,并且取决于您的实际访问模式,这可能就足够了。

您可能不高兴能够在生产系统中实现停机,重组表等功能。

通过视图执行访问,使您可以在基础表中从A / B / C切换到A / B / C / D到A / B / D,而只需很少的更改,就不会移动数据。视图对读取逻辑是透明的,并且如果您的dbms支持功能或可更新视图,那么对写入逻辑也是透明的。

确实,我认为您的决定会反映出现实世界中的许多担忧:1)什么是C和D数据类型2)为C / D收集的相对数据量3)C / D数据与纯C或D条目相比的相对重叠4)停机/维护窗口的可用性和持续时间5)DBMS支持可更新的视图6)希望将ORM中的数据库物理结构详细信息保持为透明,而通过db中的视图/功能进行呈现使其透明(对于所有访问都是相同的)应用程序,而不仅仅是当前的应用程序)

我的答案更适合(1)的大型/复杂数据类型,(3)的重叠少和(4)的停机时间最短,理想情况下,在(5)中具有良好的dbms支持,并且在(6)中有多个应用程序访问数据

但是对于很多替代品来说没有对/错:-从A / B / C开始,以后添加D,调整ORM,再到后来删除列C-从A / B / C / D开始并且忽略null等。我认为,考虑您的解决方案以及您对它的预期用途/生命周期的了解,进行一些大小/体积建模,并期望稍后进行更改,因为并非所有事物都能按预期实现。


1

删除引用并孤立数据是低风险的选择。

数据总是存在未知的“后门”用途,而通过删除该列可能很难或可能不重要。

根据数据库中C列的内容,如果数据库内部进行全表扫描或在连接期间尝试将整个表拉入内存(如果优化器认为这样做比使用索引更有效),则可能会出现较小的性能问题。

应用程序可能会读取整个表一次,而不是读取选定的列-但是,如果您仅使用ORM,则不太可能。


1

这里要考虑很多事情,但是您可能需要考虑添加视图以覆盖表格,而不是直接对表格进行更改。这样,只有视图需要改变。

我不知道Django ORM,但这是有可能的。


2
OP表示他们正在使用Postgres。
TripeHound

谢谢-没有看到标签。我将编辑Q.
罗比迪

0
  • 您有一个具有列a,b,c的表A。
  • 用列a,b,d创建一个新的表B。
  • 将数据迁移到表B。
  • 将您的外键移到表A到表B。

现在,您可以使用表B,但您仍然可以使用旧数据作为参考。

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.