SQL Server ALTER 字段 NOT NULL 需要很长时间
我想更改大约有 400 万条记录的表中的字段。 我确保所有这些字段值都不为空,并且想要将此字段更改为非空
ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL
......似乎需要永远进行此更新。 有什么方法可以加快速度,还是我只能在下班时间过夜?
这也可能导致表锁吗?
I want to alter a field from a table which has about 4 million records. I ensured that all of these fields values are NOT NULL and want to ALTER this field to NOT NULL
ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL
... seems to take forever to do this update. Any ways to speed it up or am I stuck just doing it overnight during off-hours?
Also could this cause a table lock?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以更改字段并使其不为空,而无需检查字段。 如果您真的担心不在下班时间执行此操作,您可以向该字段添加一个约束,以检查以确保它不为空。 这将允许您使用不检查选项,而不是让它检查 400 万行中的每一行以查看其是否更新。
实际上,您有两个选项(添加了第三个选项,请参阅编辑):
根据您的具体情况,任一选项可能更适合您。 我不会选择这个选项,因为你必须在下班时间运行它。 从长远来看,与你为了节省几个小时而走捷径可能面临的麻烦相比,你在半夜更新的时间是值得的。
话虽如此,如果您打算选择第二种,您可以最大限度地减少在下班时间所做的工作量。 由于您必须确保在更改列之前将行更新为不为空,因此您可以编写一个游标来慢慢地(相对于一次完成所有操作)
这将需要一段时间,但它不会锁定整个表并阻止其他程序访问它。 (不要忘记 with(rowlock) 表提示!)
编辑:我只是想到了第三种选择:
您可以创建一个包含适当列的新表,然后将原始表中的数据导出到新表。 完成此操作后,您可以删除原始表并将新表的名称更改为旧表。 为此,您必须禁用对原始依赖项的依赖项,并在完成后将它们重新设置到新依赖项上,但此过程将大大减少您在非工作时间必须完成的工作量。 这与您通过 Management Studio 对表进行列排序更改时 sql Server 使用的方法相同。 对于这种方法,我会分块进行插入,以确保不会对系统造成撤消压力并阻止其他人访问它。 然后在下班时间,您可以删除原来的,重命名第二个,并应用依赖项等。您仍然会有一些下班时间的工作,但与其他方法相比,它会微不足道。
链接到使用 sp_rename。
You can alter a field and make it not null without it checking the fields. If you are really concerned about not doing it off hours you can add a constraint to the field which checks to make sure it isn't null instead. This will allow you to use the with no check option, and not have it check each of the 4 million rows to see if it updates.
Really you have two options (added a third one see edit):
Depending on your specific scenario, either option might be better for you. I wouldn't pick the option because you have to run it in off hours though. In the long run, the time you spend updating in the middle of the night will be well spent compared the headaches you'll possibly face by taking a short cut to save a couple of hours.
This all being said, if you are going to go with option two you can minimize the amount of work you do in off hours. Since you have to make sure you update the rows to not null before altering the column, you can write a cursor to slowly (relative to doing it all at once)
This will take a good while, but it won't lock the whole table block other programs from accessing it. (Don't forget the with(rowlock) table hint!)
EDIT: I just thought of a third option:
You can create a new table with the appropriate columns, and then export the data from the original table to the new one. When this is done, you can then drop the original table and change the name of the new one to be the old one. To do this you'll have to disable the dependencies on the original and set them back up on the new one when you are done, but this process will greatly reduce the amount of work you have to do in the off hours. This is the same approach that sql server uses when you make column ordering changes to tables through the management studio. For this approach, I would do the insert in chunks to make sure that you don't cause undo stress on the system and stop others from accessing it. Then on the off hours, you can drop the original, rename the second, and apply dependencies etc. You'll still have some off hours work, but it will be minuscule compared to the other approach.
Link to using sp_rename.
据我所知,“快速”(*)执行此操作的唯一方法是
您可能希望在事务之外执行最后一步,因为这可能需要相当多的时间,具体取决于引用此表的表的数量和大小,第一步获胜根本不需要太多时间
与往常一样,最好先在测试服务器上进行测试运行 =)
PS:请不要试图使用 NOCHECK 重新创建 FK,这会使它们变得徒劳,因为优化器不会信任在构建查询计划时也不考虑它们。
(*:快速归结为:尽可能减少停机时间)
The only way to do this "quickly" (*) that I know of is by
You might want to do the last step outside of the transaction as it might take quite a bit of time depending on the amount and size of tables referencing this table, the first steps won't take much time at all
As always, it's probably best to do a test run on a test-server first =)
PS: please do not be tempted to recreate the FK's with NOCHECK, it renders them futile as the optimizer will not trust them nor consider them when building a query plan.
(*: where quickly comes down to : with the least possible downtime)
抱歉让您灰心,但是:
与您没有直接关系(因为它是关于从 NOT NULL 到 NULL),但有关此主题的有趣阅读:http://beyondrelational.com/blogs/sankarreddy/archive/2011/04/05/ is-alter-table-alter-column-not-null-to-null-always-expense.aspx
最后是一些古老的历史 - 在 2005 年论坛上的一个类似问题上,@ 提出了相同的建议Kevin 在上面提供了 - 使用约束而不是使列本身不可为空: http:// /www.sqlteam.com/Forums/topic.asp?TOPIC_ID=50671
Sorry for the discouragement, but:
Not directly relevant to you (because it's about going from NOT NULL to NULL), but interesting read on this topic: http://beyondrelational.com/blogs/sankarreddy/archive/2011/04/05/is-alter-table-alter-column-not-null-to-null-always-expensive.aspx
And finally some ancient history - on an equivalent question in a forum in 2005, the same suggestion was made as @Kevin offered above - using a constraint insteadof making the column itself non-nullable: http://www.sqlteam.com/Forums/topic.asp?TOPIC_ID=50671