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

更改大型SQL Server数据库中的列大小会导致问题,sql,sql-server,azure-sql-database,Sql,Sql Server,Azure Sql Database,我有一个超过6亿条记录的表和一个NVARCHAR(MAX)列 我需要将列大小更改为固定大小,但对于这个大数据库,我通常有两个选项: 在SSMS中使用设计器进行更改,这需要很长时间,可能永远不会完成 使用altercolumn更改它,但是之后数据库就不工作了,可能是因为我们有几个索引 我的问题是:有什么可能的解决方案可以在没有错误的情况下达到预期的结果 注意:我在Azure上使用SQL Server,该数据库正在生产中 多谢各位 澄清:我实际上拥有我想要放入的新长度范围内的所有当前数据在Azu

我有一个超过6亿条记录的表和一个
NVARCHAR(MAX)

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

  • 在SSMS中使用设计器进行更改,这需要很长时间,可能永远不会完成
  • 使用
    altercolumn
    更改它,但是之后数据库就不工作了,可能是因为我们有几个索引
我的问题是:有什么可能的解决方案可以在没有错误的情况下达到预期的结果

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

多谢各位


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

在Azure上从未这样做过,但在SQL Server上有一亿行

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

在Azure上从未这样做过,但在SQL Server上使用了一亿行

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

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

SSM将在幕后做的是

  • 为列创建具有新数据类型的新表
  • 将所有数据从原始表复制到新表
  • 用旧名称重命名新表
  • 放下旧桌子
  • 重新创建新表上的所有索引
当然,复制你所有的“超过6亿条记录”需要时间。 此外,在数据加载期间,整个表将使用(holdlock,tablockx)

使用ALTERCOLUMN对其进行更改,但之后数据库将无法工作 这可能是因为我们有几个索引

事实并非如此

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

请再想一想,更改该列的类型可以实现什么目的。如果你认为这样做会获得一些空间,那就错了

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

如果您只想将
max
更改为smth-else,例如
8000
,您将一无所获,因为这不是实际的数据大小,而只是数据可以拥有的最大大小。如果字符串大小足够小,则
nvarchar(max)
已存储为
行内数据
,而不是
行内数据
,与
ntext

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

SSM将在幕后做的是

  • 为列创建具有新数据类型的新表
  • 将所有数据从原始表复制到新表
  • 用旧名称重命名新表
  • 放下旧桌子
  • 重新创建新表上的所有索引
当然,复制你所有的“超过6亿条记录”需要时间。 此外,在数据加载期间,整个表将使用(holdlock,tablockx)

使用ALTERCOLUMN对其进行更改,但之后数据库将无法工作 这可能是因为我们有几个索引

事实并非如此

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

请再想一想,更改该列的类型可以实现什么目的。如果你认为这样做会获得一些空间,那就错了

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


如果您只想将
max
更改为smth-else,例如
8000
,您将一无所获,因为这不是实际的数据大小,而只是数据可以拥有的最大大小。如果字符串大小足够小,则
nvarchar(max)
已存储为行数据中的
,而不是像
ntext

那样存储为LOB数据,但之后数据库不工作
请始终详细说明并以文本形式发布任何错误。是否希望传递到固定长度列NCHAR(m)或者,您只想将最大可能大小更改为固定值,但将列保留为可变长度大小(我的意思是,从nvarchar(max)传递到nvarchar(m))?
但此后数据库将不工作
请始终详细说明并将任何错误作为文本发布是否要传递到固定长度的列NCHAR(m)或者,您只需将最大可能大小更改为固定值