更改大型SQL Server数据库中的列大小会导致问题

时间:2017-08-24 22:05:16

标签: sql sql-server azure-sql-database

我有一个包含超过6亿条记录和NVARCHAR(MAX)列的表格。

我需要将列大小更改为固定大小,但我通常对此大型数据库有两个选项:

  • 使用SSMS中的设计师更改它,这需要很长时间,也许永远不会完成
  • 使用Alter Column更改它,但之后数据库不起作用,可能是因为我们有几个索引

我的问题是:有什么可能的解决方案可以毫无错误地实现预期的结果?

注意:我在Azure上使用SQL Server,此数据库正在生产中

谢谢

澄清:我实际上拥有了我想要放置的新长度范围内的所有当前数据

2 个答案:

答案 0 :(得分:1)

从未在Azure上执行此操作,但在SQL Server上使用了数亿行。

我将添加一个所需大小的新列,当然允许空值并创建所需的索引。 之后,我将以块的形式更新这个新列修剪/将旧列值转换为新列。毕竟,删除旧列上的索引并将其删除。

答案 1 :(得分:1)

  

使用SSMS中的设计器更改它,这需要很长时间   也许永远不会结束

SSMS将在幕后做什么

  • 使用列的新数据类型创建一个新表
  • 将原始表中的所有数据复制到newe表
  • 使用旧名称重命名新表
  • 放弃旧桌
  • 重新创建新表上的所有索引

当然,复制所有“超过6亿条记录”需要时间。 此外,整个表将在数据加载期间锁定with (holdlock, tablockx)

  

使用Alter Column更改它,但之后数据库不起作用   那可能是因为我们有几个索引

事实并非如此。

如果涉及任何索引,并且只有那个字段ad included列的索引由于其数据类型为nvarchar(max),则服务器会给您一个错误,并且在您丢弃之前不会执行任何操作那个指数。如果没有索引受到影响,它就不能“在那之后不起作用,也许是因为我们有几个索引”。

请再想一想您希望如何更改该列的类型。如果你认为你会获得一些空间,那就错了。

nvarchar(max)传递到nchar(max)(从可变长度类型到固定长度类型)后,您的数据将占用比现在更多的空间,因为即使列具有固定数量的字节也是如此null或1-2-3个字符。

如果您只想将max更改为其他内容,例如8000,则无法获得任何结果,因为这不是真正的数据大小,而只是数据可以拥有的最大大小。如果您的字符串大小足够小,则nvarchar(max)已存储为in-row data,而不是LOB data,而不是ntext