将字母数字字段作为主键可以吗?

时间:2012-07-20 11:26:21

标签: c# asp.net sql vb.net database-design

我正在重写一个新的时间表应用程序,包括重新设计数据库,它需要从Oracle到Oracle的数据迁移。

在旧系统字段中,“EmployeeCod”是主键,它是字母数字形式,即'UK001','UK002','FR001','FR002','US001'。 Employee表还链接到时间表和其他表,其中EmpCode被称为FK。

为了使JOIN在新系统中执行得更快,我考虑在Employee表中添加一个新的INT列并将其设置为PK。 (不知道它是否会产生很大的不同)

- 员工表约有600行。

- EmpCode的数据类型是旧数据库中的Varchar2(20),我可以在新系统中将其缩减为Varchar2(6),并在公司消费时稍后进行更改。

  

我想知道将EmpCode保留为主键是否更好,这会使迁移数据变得更容易,还是应该添加INT列?

有人在我之前的一个帖子中给了我以下建议:

“如果您需要创建AANNN的复合代码,那么我将其拆分为两个:CHAR(2)的简单'前缀'字段和INT的标识字段,然后将EmpCode转换为连续的计算字段两个并在那里贴上一个指数(@Chris)“

我不确定此选项是否可行,因为员工表也链接到其他表。 (EmpCode在其他表中用作FK) Ñ

5 个答案:

答案 0 :(得分:1)

如果您在字母数字字段上创建的索引是表的聚簇索引,则性能差异可以忽略不计。根据你的问题,情况就是这样,但我想注意完整性。我说这有两个原因:

  1. 聚集索引是表的物理顺序,因此在查询该索引时,在查询中查找可能 off the data page 的更多数据时,可以对其执行二进制搜索因为它也按照那个顺序进行物理存储。
  2. 二元搜索效率与您可以获得的效率差不多,以免我们忘记统计索引。我之所以这样称呼是因为整数主键构建的统计索引与您可以获得的搜索速度一样快,因为从数学上讲,我们知道 2就是在1之后。
  3. 因此,在构建字母数字,甚至复合键和索引并尝试比较它们与整数键之间的差异时,请记住这一点。就个人而言,我更喜欢坚持使用整数主键,因为我发现它们在极端增长期间会随着时间的推移而表现更好。

    我希望这会有所帮助。

答案 1 :(得分:1)

我经常使用字母数字主键,绝对没有问题。没有性能问题,您有更广泛的可寻址空间,并且您可以更具表现力/人性化。整数键只是一种约定。

通过在移植问题之外添加主要的体系结构更改来增加您添加到项目中的风险,我会说尽可能坚持使用现有模式。

答案 2 :(得分:1)

没有性能提升 - 事实上,除非你知道并且可以证明/衡量你有性能问题,否则改变“使它们更快”通常会导致痛苦。

然而,有人担心您的主键似乎带有意义 - 它是一个国家代码,与数字连接在一起。如果员工从美国搬到英国怎么办?如果英国雇佣了第1000名员工怎么办?

出于这个原因,我会重构应用程序以使用无意义的主键;无论是INT还是VARCHAR都不是很重要。

答案 3 :(得分:1)

如果您确实添加了此PK,并且还保留了以前的PK,那么您将遇到一些数据管理问题需要处理。或者也许是您的客户。如果现有用户将升级到新数据库,那么摆脱旧的PK可能是不可行的。

如果EmployeeCode,数据用户使用前PK来识别Employees,那么您必须添加一个约束以确保该字段是唯一的。携带这两个代码将消除您希望的任何性能提升。

如果是我,我会独自离开。如果有的话,性能提升将是微不足道的。

答案 4 :(得分:0)

你偶尔会碰到字母数字的主键。我个人觉得它只会让生活变得更加困难..如果你能够改变它而你想改变它,我会说继续......它会让事情变得更容易为了你以后。至于它是一个FK,你需要小心编写一个脚本来正确更新所有数据。一种方法是:

Step 1: Create a new int column for the PK and set Identity Insert to true
Step 2: Add a new int column in your child table and then:
Step 3: write an update script like this:

    UPDATE childTable C
    INNER JOIN parentTable P ON C.oldEmpID = P.oldEmpID
    SET C.myNewEmpIDColumn = P.myNewEmpIDColumn

Step 4: Repeat steps 2 & 3 for all child tables
Step 5: Delete all old FK columns

类似的东西,不要忘记先备份当前的数据库;)