SQL Server,将NTEXT转换为NVARCHAR(MAX)

时间:2009-01-28 11:36:30

标签: sql sql-server sql-server-2005

我有一个包含大量字段的数据库,这些字段当前是NTEXT。

升级到SQL 2005后,我们运行了一些性能测试,将它们转换为NVARCHAR(MAX)。

如果您阅读本文:

http://geekswithblogs.net/johnsPerfBlog/archive/2008/04/16/ntext-vs-nvarcharmax-in-sql-2005.aspx

这解释了一个简单的ALTER COLUMN不会将数据重新组织成行。

我用我的数据来体验这一点。如果我们只运行ALTER COLUMN,我们在某些方面的表现实际上要糟糕得多。但是,如果我为所有这些字段运行UPDATE表SET Column = Column,那么我们将获得极大的性能提升。

我遇到的问题是数据库包含数百个具有数百万条记录的列。一个简单的测试(在低性能虚拟机上)有一个包含单个NTEXT列的表,包含700万条记录需要5个小时才能更新。

有人可以提供任何关于如何以更有效的方式更新数据以减少停机时间和锁定的建议吗?

编辑:我的备份解决方案是随着时间的推移只更新块中的数据,但是,使用我们的数据会导致性能下降,直到所有记录都更新为止,此时间越短越好,所以我仍然在寻找以便更快地进行更新。

5 个答案:

答案 0 :(得分:6)

如果你无法获得预定的停工时间......

创建两个新列: 为nvarchar(最大) processedflag INT DEFAULT 0

在processedflag上创建非聚集索引

您可以使用UPDATE TOP(您希望更新按主键排序的顶部)。

只需在更新期间将processedflag设置为1,以便下次更新只会更新已处理标志仍为0的位置

您可以在更新后使用@@ rowcount来查看是否可以退出循环。

我建议在每次更新查询后使用WAITFOR几秒钟,以便让其他查询有机会获取表上的锁,而不是使磁盘使用量过载。

答案 1 :(得分:3)

如何批量运行更新 - 一次更新1000行。

您将使用while循环来递增计数器,该循环对应于在更新查询的每次迭代中要更新的行的ID。这可能不会加快更新所有700万条记录所需的时间,但它应该会减少用户因记录锁定而遇到错误的可能性。

答案 2 :(得分:3)

如果您可以获得预定的停机时间:

  1. 备份数据库
  2. 将恢复模式更改为简单
  3. 从正在更新的表中删除所有索引
  4. 使用非聚集索引
  5. 添加列maintenanceflag(INT DEFAULT 0)
  6. 执行命令 更新TOP 1000 表名 来自ntext的SET nvarchar, maintenanceflag = 1 WHERE maintenanceflag = 0
  7. 根据需要多次(在有延迟的循环内)。

    完成后,再执行一次备份,然后将恢复模型更改回原来的状态并添加旧索引。

    请记住,该表上的每个索引或触发器都会导致额外的磁盘I / O,并且简单恢复模式可以最大限度地减少日志文件I / O.

答案 3 :(得分:1)

在低性能虚拟机上运行数据库测试并不能真正指示生产性能,所涉及的大量IO需要一个快速的磁盘阵列,虚拟化将会对其进行限制。

答案 4 :(得分:0)

您可能还会考虑测试SSIS包是否可以更有效地执行此操作。

无论您做什么,都可以将其设置为可在非工作时间安排和运行的自动化流程。您尝试访问数据的feweer用户,一切都会越快。如果可能的话,挑选最重要的三个或四个以进行更改并将数据库关闭以进行维护(在正常关闭时间内)并在单用户模式下执行。一旦你得到最关键的,其他人可以安排一晚或两晚。