sql-server-2000 - 更改 100GB 表的有效方法

标签 sql-server-2000 bulkinsert

我们有许多数据库,它们在其中一个表中存储了 10 到 100 GB 的数据。它包含图像数据。问题是许多这些数据库的创建不正确。基本上主键实际上不是主键。是使用可空列上的唯一索引创建的。其中一些将 int 作为主键而不是 bigint。

所以我们一直在慢慢地检查和修复这些数据库。它们在 SQL Server 2000 到 SQL Server 2008 上运行,尽管大多数有主键问题的都在 SQL Server 2000 上。问题是,我们不想在转换表时将数据库锁定一整天。我们经历了几种策略:

  • 告诉 SQL Server 直接更改列类型。这会锁定 table 直到它完成,并且在许多情况下将它放置一夜之后,它仍然没有完成。
  • 一次性将所有图像插入到新表格中。这更容易被中断,但整个表基本上在这个过程中被写入日志文件。
  • 在目标表中不存在行的情况下一次插入 100 行。好处是他们可以在这种情况下继续使用数据库(性能受到很大影响),并且可以在任何时候任意停止和重新启动,并且可以防止 100GB 以上的日志文件。这就是我们目前正在做的事情,但是随着目标表变得越来越大,找到不存在的前 100 行变得非常缓慢。 UPDATE STATISTICS 和 DBCC INDEXDEFRAG 有很大帮助,但在最近的尝试中,我们甚至一次有 100 张图像坐在那里没有响应。
    INSERT INTO %s  
      SELECT TOP 100 Source.*  
      FROM %s AS Source WITH (NOLOCK)  
      LEFT OUTER JOIN %s AS Target WITH (NOLOCK) ON Source.DocumentID = Target.DocumentID  
      WHERE Target.DocumentID IS NULL  
      ORDER BY Source.DocumentID  
    

  • 那么问题来了,有没有一种可以高效且可恢复的方式复制批量数据的选项?它不一定是 100% 准确,只要它完成了 99% 的工作,我们总是可以在最后返回并修复任何差异。

    最佳答案

    加入是问题所在。不要那样做。只需使用当前的聚集索引,使用一些合理的间隔循环遍历当前表。就像是:

    Declare @idrange int;
    Set @idrange = 1;
    
    WHILE @idrange < 10000000
    
    INSERT INTO Destination
      SELECT *  
      FROM Source
      WHERE DocumentID between @idrange and @idrange + 999
      ORDER BY Source.DocumentID  
    
    Set @idrange = @idrange + 1000
    End 
    

    请注意,为了获得最佳速度,请从目标表中删除所有索引(包括聚集索引),然后在插入所有行后添加索引。

    编辑 :更改范围间隔以防止重叠(因为 BETWEEN 包括端点)

    最后一个澄清:我的示例脚本的总体要点是,您只想以某种合理的顺序遍历当前记录,并将它们分批放入新表中。没有理由每次都继续检查目标表,因为您应该已经知道在那里放了什么,还剩下什么。大多数时候,使用聚集索引(如果有)是有意义的,因为这意味着它可以遍历表的物理顺序,而无需进行书签查找。如果该表没有簇,那么就使用最有意义的(可能是你的 PK)。

    关于sql-server-2000 - 更改 100GB 表的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3702701/

    相关文章:

    mysql - 使用MySQL批量插入数据库表数据

    sql-server - 需要有关在SQL Server上使用SqlBulkCopy插入信封的建议

    sql - SQL 中的数学运算?

    sql - 将 1000 列旋转/透视为行

    sql - 获取表列表但不包括系统表(SQL Server 2K)?

    ios - 如何使用 swift 将批量数据插入 iOS 中的 SQLite 数据库

    sql-server - 带有额外列的批量插入

    tsql - SQL Server 2000传输登录名和关联的服务器角色以及对特定数据库的访问

    sql - TSQL - 是否可以定义排序顺序?

    php - 从 ID 列表批量更新值列表