1

使用 MS SQL 2008,所有表都包含一个 Status varchar(1) 列,该列指示“I”表示插入记录,“U”表示更新记录,“D”表示已删除记录以及 DateCreated 日期时间列和 DateUpdated 日期时间列.

在大多数情况下,我们只想查询表中的活动记录,我们会执行以下操作:

SELECT column FROM table WHERE Status <> 'D'

为了提供对使用的看法,这是最常用的过滤器,因为它几乎出现在每个查询中,并且在连接表时出现多次。

我们正在开发一个新的 Web 应用程序和数据库,重点是最大限度地提高性能。一个建议是,从这个和未来的项目开始,将 varchar(1) 状态列模式替换为类似于“IsDeleted”的方式,以指示记录是否被删除,并从两个日期时间字段推断更新状态。

换句话说...

SELECT column as InsertedRecords FROM table WHERE Status = 'I' -- Rare case
SELECT column as UpdatedRecords FROM table WHERE Status = 'U' -- Rare case
SELECT column as ActiveRecords FROM table WHERE Status <> 'D'
SELECT column as DeletedRecords FROM table WHERE Status = 'D'

......反而看起来像......

SELECT column as InsertedRecords FROM table WHERE IsDeleted = 0 AND DateCreated = DateUpdated -- Rare case
SELECT column as UpdatedRecords FROM table WHERE IsDeleted = 0 AND DateCreated <> DateUpdated -- Rare case
SELECT column as ActiveRecords FROM table WHERE IsDeleted = 0
SELECT column as DeletedRecords FROM table WHERE IsDeleted = 1

是否有任何切实的性能优势/影响(主要围绕索引和大型查询)或者两种实现都完全可以接受?为了一致性而继续当前模式以使它们与先前创建的应用程序/数据库保持一致是否有任何缺点?

4

2 回答 2

1

我认为仅仅使用 bit 列而不是 char(1) 列并没有太大的损失或收益。

在索引方面,仅位列上的索引不会给您带来太多价值,因为它可能只有 2 个可能的值:1 和 0(我假设您的列不可为空)。

带有WHERE条件的查询DateCreated <> DateUpdated不能很好地工作,因为它不能有效地使用索引,并且很可能表现得比您现有的 char(1) 字段更差。

总而言之,我认为您现有的解决方案将比位字段和日期字段更好。如果您想使用数字,您可以将值存储在 tinyint 字段中(例如 I = 0、U = 1、D = 2)。

您还可以做两件事来提高性能:

  • IsDeleted根据您运行的查询(例如 on和DateCreated)基于 bit/char 列和其他列创建索引
  • 在索引中包含返回的列SELECT,这样查询就不必从表中查找记录。
于 2013-10-04T00:22:27.373 回答
1

无需过多介绍(您可以自己查找),其他提高非选择性数据性能的方法是:过滤索引和表分区。

例如,如果您正在寻找其中的精确数据,WHERE Status <> 'D'那么这可能会受益于过滤索引。基本上它只索引您感兴趣的记录,使索引更小(并且可能更快)

就我个人而言,我更喜欢 I/U/D 模式而不是位模式,因为对我来说它是“正交的”,这是我习惯的。

此外,如果您不经常查看已删除的记录,您可能希望将它们拆分到不同的分区中。它对用户是透明的(他们只看到一个表),但在幕后你实际上可以把它放在一个较慢的便宜的磁盘上,少备份它等等。它也知道去哪个分区并且不费心去查看另一个(已删除)分区。

如果您很少使用这些已删除记录,我还会考虑为什么您将这些已删除的记录弄得乱七八糟。也许您可以将它们移动到数据仓库并在那里报告表格。

于 2013-10-04T01:52:28.930 回答