我正在解决由第三方建立的新数据库中的问题。
侧面注意:我刚刚加入了最初雇用第三方的公司。新的数据库不到两周,并且是在我上班的头几天启动的。
该数据库应该与旧数据库的架构匹配,但是不幸的是,第三方忘记了包含一些约束,触发器和索引。
两个数据库均为SQL Server 2012
我想更改一个当前不具有旧模式中主键的表。下面是简化的创建表语句
当前产量
CREATE TABLE [dbo].[Table](
[field] [varchar](255) NULL,
[data] [varchar](255) NULL,
[id] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
GO
旧数据库中的表
CREATE TABLE [dbo].[Table](
[id] [int] NOT NULL,
[field] [varchar](255) NULL,
[data] [varchar](255) NULL,
PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
这对ALTER生产表并重新添加主键以及旧数据库中存在的索引是否有重大影响?是否有最佳实践指南?
这是用于更改生产表的适当SQL
ALTER TABLE [dbo].[Table] ADD PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
考虑到查询将需要执行的处理,我将在下班时间运行Alters。我决定使用ALTER,而不是清空表并根据环境的业务需求重新填充表。
通过使用此查询,我已确认IDENTITY列当前为唯一
SELECT DISTINCT(id), COUNT(id)
FROM Table
GROUP BY id
HAVING Count(id) > 1
如果上述情况仍然成立,那么我将在非高峰时段运行以下程序:
ALTER TABLE [dbo].[Table] ADD CONSTRAINT PK_Table PRIMARY KEY CLUSTERED
(
[id] ASC
)
答案 0 :(得分:0)
CLUSTERED INDEX
的开销很大。这将迫使页面重新排序,这意味着它将占用大量的IO,这取决于表可能需要一些时间。如果这样的话,很可能会锁定表一段时间。是的,这是正确的语法,但是,我建议给您的Key命名。这会将语法更改为:
ALTER TABLE [dbo].[SampleTable] ADD CONSTRAINT PK_SampleTable PRIMARY KEY CLUSTERED (ID ASC);
恐怕我们无法回答其他人的决定。
答案 1 :(得分:0)
不能保证SQL Server中的标识列是唯一的。正如documentation明确规定的那样:
列上的identity属性不能保证满足以下条件:
- 值的唯一性-必须通过使用PRIMARY KEY或UNIQUE约束或UNIQUE索引来强制唯一性。
几乎总是将标识列声明为主键,但并非必须如此。
第二,如果确实将列设为主键,则通常将其聚集(除非已经存在另一个聚集索引)。如documentation中所述:
创建主键会自动创建相应的唯一聚集索引,如果指定了聚集索引,则将创建非聚集索引。
我猜想您希望将Identity列视为主键。您应该这样定义。您可以尝试将主键约束添加到现有表中(保持双手交叉,确保没有列重复)。
您可能会发现清空表,添加正确的约束并重新加载数据的性能更高。
如果您有主键,则有充分的理由将其用作标识列-这有助于避免页面碎片。新值永远不会小于现有值,因此新行将出现在“最后一个”数据页面上。
答案 2 :(得分:0)
这将是昂贵的操作,但这取决于表中的数据量和您执行的时间。
为主键提供名称,而不是由系统生成匿名名称。
想到表和数据的目的是什么?它在哪里使用?