是否激活标志?

时间:2020-03-06 14:26:11  来源:igfitidea点击:

好的,因此实际上每个基于数据库的应用程序都必须处理"非活动"记录。软删除或者将某些内容标记为"要忽略"。我对"活动"列(或者状态列)上是否有任何激进的替代想法感到好奇。

例如,如果我有一个人名单

CREATE TABLE people (
  id       INTEGER PRIMARY KEY,
  name     VARCHAR(100),
  active   BOOLEAN,
  ...
);

这意味着要获得活跃人群的列表,我们需要使用

SELECT * FROM people WHERE active=True;

有谁建议将非活动记录移到单独的表中,并在适当的位置将UNION合并为两个?

好奇心惊人...

编辑:我应该明确地说,我是从纯粹主义者的角度出发的。我可以看到对于大量数据可能需要进行数据归档,但这不是我要从哪里来的。如果我们执行SELECT * FROM people,那么对我来说这些条目在某种意义上是"活动的"

谢谢

解决方案

我们经常使用活动标志。但是,如果数据库很大,那么我可以看到将非活动值迁移到单独表中的值。

这样,仅当某人希望查看所有活动或者非活动记录时,才需要对表进行合并。

好吧,为确保仅在大多数情况下绘制活动记录,可以创建仅包含活动记录的视图。这样,不遗漏活动部分会容易得多。

活动标志有点丑陋,但它很简单并且效果很好。

我们可以按照建议将它们移动到另一个表。我建议查看活动/非活动记录的百分比。如果我们有20%或者30%以上的非活动记录,则可以考虑将其移至其他位置。否则,这没什么大不了的。

在大多数情况下,指示删除的二进制字段已足够。通常,存在一种清理机制,该机制会在一定时间后删除那些已删除的记录,因此我们可能希望使用已删除的时间戳来启动架构。

移到单独的桌子上并重新备份它们需要花费时间。根据脱机记录的数量以及需要多久将它们恢复一次,这可能是一个好主意,也可能不是一个好主意。

如果大多数人一旦被埋葬就不回来,并且仅用于汇总/报告/其他内容,那么它将使主表更小,查询更简单并且可能更快。

是的,我们会的。当前,我们许多表中都有" active ='T / F'"列,主要用于显示"最新"行。插入新行时,前一个T行被标记为F,以保留该行以进行审核。

现在,我们将移至2表方法,当插入新行时,前一行将移至历史记录表。对于大多数查看当前数据的案例,这可以为我们提供更好的性能。

成本比以前的方法略高,以前我们必须更新和插入,而现在我们必须进行插入和更新(即,不是插入新的T行,而是使用所有新数据来修改现有行),因此成本只是传递整行数据,而不是仅仅传递更改。这几乎不会产生任何效果。

性能优势在于主表的索引明显较小,并且我们可以更好地优化表空间(它们的增长不会太大!)

我们在活动标志上对表进行分区,以便活动记录位于一个分区中,而非活动记录位于另一分区中。然后,为每个自动创建活动过滤器的表创建一个活动视图。数据库查询引擎自动将查询限制在其中具有活动记录的分区,这比在该标志上使用索引要快得多。

这是如何在Oracle中创建分区表的示例。 Oracle没有布尔列类型,因此出于Oracle的目的,我修改了表结构。

CREATE TABLE people
(
   id       NUMBER(10),
   name     VARCHAR2(100),
   active   NUMBER(1)
)
PARTITION BY LIST(active)
(
   PARTITION active_records VALUES (0)
   PARTITION inactive_records VALUES (1)
);

如果需要,可以将每个分区放在不同的表空间中。我们还可以对索引进行分区。

顺便说一句,这似乎是这个问题的重复,作为一个新手,我需要问一下,处理意外重复的过程是什么?

编辑:根据注释中的要求,提供了在Oracle中创建分区表的示例

我们使用两种方法来处理非活动记录。我们使用的方法取决于情况。对于本质上是查询值的记录,我们使用活动位字段。这使我们可以停用条目,使它们不被使用,但也可以使我们与关系保持数据完整性。

我们使用"移至分离表"方法,在该方法中不再需要数据并且该数据也不是关系的一部分。

该方法确实决定了解决方案,方法是:

如果表包含用户,则可以使用几个"标志"字段。一个用于"已删除","已禁用"等。或者如果空间不足,那么一个"已禁用"标志就足够了,如果已删除该行,则实际上将其删除。

它还取决于用于存储数据的策略。如果有保留数据存档的策略,那么很长一段时间后很可能需要一个单独的表。

不,这是很常见的事情,具体取决于特定要求(但是我们已经介绍了它们):

1)如果我们希望拥有完整的BUNCH数据(例如多个TB或者更多),则立即存档已删除的记录不是一个坏主意,尽管我们可以使用标记为已删除然后复制到存档表的组合方法。

2)当然,尽管我们的开发人员往往是数据包鼠,但硬删除记录的选项仍然存在,我建议我们应该查看业务流程并确定是否有必要甚至保留数据所以……如果没有,我们应该可以根据特定的业务场景,随意地将这些东西扔掉……再次。

我们在大多数表中都使用了enum('ACTIVE','INACTIVE','DELETED'),因此实际上我们有一个3向标记。我发现它在不同情况下都对我们有效。你的旅费可能会改变。

移动不活跃的东西通常是一个愚蠢的主意。这样做的开销很大,而且有很多潜在的错误,所有事情都变得更加复杂,例如将内容取消存档等。我们如何处理相关数据?如果也移动所有这些内容,则必须修改每个查询。如果我们不移动它,我们希望获得什么优势?

这引出了下一个要点:为什么要移动它?当大小加倍时,正确索引的表需要进行一次额外的查找。任何性能改进都可以忽略不计。为什么还要考虑到遥远的将来,当我们实际遇到性能问题时呢?

我认为严格将其视为一条数据,然后按照原始帖子中显示的方式进行操作是正确的。活动标志数据直接取决于主键,应位于表中。

该表保留有关人员的数据,而不管其数据的当前状态如何。

从"纯粹的观点"来看,现实模型并没有区分视图和表格两者都是关系。因此,只要实体名称正确,例如,使用区分符的视图的使用就完全有意义且有效。人员/活动人员。

同样,从"纯粹的角度"看,表应该命名为person,而不是people,因为关系的名称反映的是元组,而不是整个集合。

在模式中,像这样的二进制标志是一个糟糕的主意。考虑查询

SELECT count(*) FROM users WHERE active=1

看起来很简单。但是,当我们有大量用户时,会发生什么情况,以至于需要向该表添加索引。同样,它看起来直截了当

ALTER TABLE users ADD INDEX index_users_on_active (active)

除了!!该索引是无用的,因为此列的基数恰好是2!任何数据库查询优化器都将忽略此索引,因为它的基数很低,并进行表扫描。

在使用有用的标志填充架构之前,请考虑如何访问该数据。

https://stackoverflow.com/questions/108503/mysql-advisable-number-of-rows