向现有的唯一列添加主键约束

Gen*_*ari 5 sql-server constraint primary-key

我已经看到很多关于向大型数据库表添加新主键列的信息,但我的情况有些不同。

我有一个没有主键的大表(约 90,000,000 条记录)。但是,它确实有一个“RowID”列,它是一个标识列。它还在 RowID 列上有一个唯一索引。

我所有的研究都表明,没有主键的表是一种糟糕的设计,如果可能的话应该去掉。在我的特殊情况下;这会导致问题,因为如果找不到主键,实体框架会将表映射为只读视图。

我想在 RowID 列上的表中添加一个主键约束。我希望因为它没有添加新列,并且该列上已经有一个唯一索引,所以这将是一个小操作;然而,从测试运行来看,这将需要很长时间。

长时间无法访问此表会导致整个业务出现问题。我知道另一种选择是使用新模式创建一个新表,并将所有数据从旧数据复制到新数据。但这也会导致我们需要长时间锁定表。

当您已经有一个带有唯一索引的标识列时,有没有办法更快地添加主键约束?

小智 1

您的假设是创建新表时会发生锁定。如果您使用正确的查询提示并制定良好的行动计划,则这是错误的。我推荐以下内容:

  1. 创建一个具有相同架构但添加了主键约束的新表。
  2. INSERT INTO NewTable SELECT * FROM OldTable (这仍然需要一段时间)
  3. 使用 SSIS 或编写一个好的函数来识别旧表中的新行,同时插入新表并将这些行写入新表。(本质上是在上面执行另一个合并)
  4. 重命名/删除旧表并将新表重命名为旧表名称。

关于锁的话题。正如我所见,你有几个选择:

  1. 在查询中指定 NOLOCKS 或 READUNCOMITTED。这有其自身的含义,最好在这里阅读阅读。
  2. 采取全表锁定,您已经说过这种做法不太理想,但这意味着不需要行动计划的第 3 步。
  3. 采取共享页面锁定(select 的默认值)。这意味着读取时各个页面将被锁定,并且不允许更新或插入。这确实意味着在此锁定期间仍然可以发生此页面上的其他选择。

这实际上取决于您的具体需求,这三个中哪一个是您最好的 COA。我建议咨询业务部门以确定中断是否真的是一件坏事,如果是,请咨询开发人员以确定最适合该任务的锁定级别。

  • @GendoIkari您的第一点只是语义 - 出于所有意图和目的,唯一索引或唯一约束的行为与主键相同。通过使用这些构造之一,您并没有犯下任何可怕的设计犯罪。对于你的第二点,是的,像 EF 这样的 ORM 遵循 80/20 规则并迎合最低公分母。不幸的是,大多数用户实际上需要做这 20% 类别中的很多事情。 (2认同)
  • 在 EF Code-First 中,您可以将键列声明为唯一索引的列。这只是寻找 PK 的自动逆向工程代码。 (2认同)