3

假设我有一个用户,它有一个状态,用户的状态可以是“活动”、“暂停”或“非活动”。

现在,在创建数据库时,我想知道......最好有一个带有字符串值的列(使用枚举类型或应用规则),以便更容易查询和了解当前用户状态或连接更好,我应该加入包含可能的用户状态的 UserStatuses 表?

假设,当然状态不能由应用程序用户创建。

编辑:一些澄清

  1. 不会使用字符串连接,它将是 UserStatuses PK 的 int 连接
  2. 我主要关心的是性能方面
  3. 可能的状态是静态的并且永远不会改变
4

5 回答 5

2

在大多数系统上,它对性能几乎没有影响。就个人而言,为了清楚起见,我会使用一个短字符串,并将其连接到一个更详细的表格中,如您所建议的那样。

create table intLookup
(
pk integer primary key,
value varchar(20) not null
)
insert into intLookup (pk, value) values
(1,'value 1'),
(2,'value 2'),
(3,'value 3'),
(4,'value 4')

create table stringLookup
(
pk varchar(4) primary key,
value varchar(20) not null
)

insert into stringLookup (pk, value) values
(1,'value 1'),
(2,'value 2'),
(3,'value 3'),
(4,'value 4')



create table masterData
(
stuff varchar(50),
fkInt integer references intLookup(pk),
fkString varchar(4)references stringLookup(pk)
)
create index i on masterData(fkInt)
create index s on masterData(fkString)

insert into masterData
(stuff, fkInt, fkString)
select COLUMN_NAME, (ORDINAL_POSITION %4)+1,(ORDINAL_POSITION %4)+1 from INFORMATION_SCHEMA.COLUMNS
go 1000

这会产生 300K 行。

select 
*
from masterData m inner join intLookup i on m.fkInt=i.pk

select 
*
from masterData m inner join stringLookup s on m.fkString=s.pk

在我的系统(SQL Server)上——查询计划、I/O 和 CPU 是相同的——执行时间是相同的。- 查找表被读取和处理一次(在任一查询中)

使用 int 或字符串没有区别。

于 2013-11-13T21:44:37.747 回答
2

我认为,作为一个整体,每个人都已经找到了你问题答案的重要组成部分。但是,它们都有优点,应该一起考虑,而不是分开考虑。

  1. 正如逻辑学家所提到的,健康的标准化通常被认为可以提高性能。但是,与逻辑学家相反,我认为您的情况是正常化的最佳时机。您的问题似乎是标准化之一。在这种情况下,使用 Santhosh 建议的数字键,然后返回到包含状态解码的代码表,这将导致每条记录存储的数据更少。这种差异不会显示在小型 Access 数据库中,但它可能会显示在包含数百万条记录的表中,每条记录都有一个状态。

  2. 正如 David Aldridge 所建议的那样,您可能会发现对这个特定数据点进行规范化会导致最终用户体验更加可控。规范化状态字段还允许您稍后在一个位置编辑状态标志,并使该更改在整个数据库中永久存在。如果您的老板和我一样,那么您可能需要将“非活动状态”更改为“已关闭”(然后下周再返回!),如果状态字段未标准化,这将是更多工作。通过规范化,也更容易实施参照完整性。如果状态码表中没有状态键,则无法将其添加到主表中。

  3. 如果您在将来查询时担心性能,那么需要考虑一些不同的事情。要拉回状态,如果它已标准化,您将在查询中添加一个联接。该连接可能不会对任何大小的记录集造成伤害,但我相信它会通过限制必须处理的原始文本数量来帮助更大的记录集。如果您主要关心的是查询数据时的性能,这里有一个关于如何优化查询的好资源:http ://www.sql-server-performance.com/2007/t-sql-where/我想你会发现这里讨论的许多规则也将适用于您在连接本身中强制执行的任何包含标准。

希望这可以帮助!

克里斯托弗

于 2013-11-13T22:30:34.000 回答
1

标准化背后的整个想法是防止数据重复(至少是其中一个概念)。

在这种情况下,用户一次只能拥有 1 个状态(我假设),因此他们没有理由将其放在自己的表中。你只会让事情复杂化。你会有一个单独的表的唯一原因是如果由于某种原因这些状态不是静态的。这意味着下个月您可以添加“排序活跃”和“可能不活跃”。如果您没有将它们放在自己的表中,这将意味着更改代码以弥补这一点。您可以创建一个维护页面,用户可以在其中添加状态,然后需要您创建一个单独的表。

于 2013-11-13T21:56:19.500 回答
1

需要考虑的一个问题是这些状态值是否具有它们自己的属性。

例如,您可能希望有一个与状态文本的字母顺序不同的默认排序顺序。您可能还希望以不对待另一个的特定方式处理其中两个状态,这可能是一个属性。

如果您有需要,或者怀疑将来需要,则将状态文本移动到不同的表并为它们使用整数键值。

于 2013-11-13T22:10:30.857 回答
0

我建议使用整数值,例如 0、1、2。如果这是固定的。在解释报告中的结果时,我们可以将这些状态改回字符串。

于 2013-11-13T22:00:57.207 回答