【问题标题】:Delete All / Bulk Insert全部删除/批量插入
【发布时间】:2011-04-30 19:12:15
【问题描述】:

首先让我说我在 SQL Server 2005 上运行,所以我无权访问 MERGE

我有一个大约 150k 行的表,我每天都会从文本文件中更新它。当行从文本文件中删除时,我需要将它们从数据库中删除,如果它们发生变化或者是新的,我需要相应地更新/插入。

经过一些测试,我发现在性能方面,执行完全删除然后从文本文件批量插入比逐行读取文件执行更新/插入要快得多。然而,我最近看到一些帖子讨论使用临时表和 UPDATE 语句的输出来模仿 SQL Server 2008 的 MERGE 功能。

我对此很感兴趣,因为我正在研究如何在表没有行时消除删除/批量插入方法中的时间。我仍然认为这种方法会最快,所以我正在寻找解决空表问题的最佳方法。

谢谢

【问题讨论】:

    标签: sql sql-server sql-server-2005 performance bulkinsert


    【解决方案1】:

    我认为您最快的方法是:

    1. 删除所有外键和索引 从你的桌子上。
    2. Truncate你的 表。
    3. 批量插入数据。
    4. 重新创建外键并 索引。

    【讨论】:

    • 感谢您的提示,我不知道 Truncate 并且可能会使用它,但我试图消除表为空时删除和批量插入之间的短时间段。有什么想法吗?
    • @rpf3:试试 TRUNCATE。我认为这将消除您所说的大部分延迟。
    • 截断肯定比删除快,但批量插入仍然需要大约 9 秒。我被问到是否有办法消除这种少量的停机时间,因为其他进程可能会在运行时访问数据库。
    • @rpf3:如果您已经按照我给出的步骤进行操作,那么我不知道还有什么可以加快速度的。老实说,在我看来,每天一次批量插入 150K 行需要 9 秒。
    • @rpf3:您可以批量插入临时表并尝试sp_rename 之类的操作,我认为这需要一个同样有害的表锁。您可以尝试创建表的两个版本并创建一个视图,该视图将在两个版本之间交替,而另一个版本是批量插入的。但最终,我的直觉是,将一些重试/异常处理逻辑编码到这些自动化流程中可能更安全、更容易。
    【解决方案2】:

    问题是 Joe 的解决方案不够快,还是您的进程运行时无法针对目标表进行任何活动?如果您只需要阻止用户对您的目标表运行查询,您应该将您的进程包含在事务块中。这样,当您的 TRUNCATE TABLE 执行时,它将创建一个表锁,该锁将在事务期间保持,如下所示:

    begin tran;
    
    truncate table stage_table
    
    bulk insert stage_table
    from N'C:\datafile.txt'
    
    commit tran;
    

    【讨论】:

    • 我正在考虑这样做,但如果您没有访问数据文件或格式文件的权限,则会引发 SQL TRY/CATCH 无法捕获的错误,并将停止代码中间事务,让它保持打开状态。
    【解决方案3】:

    另一种解决方案可以满足您对正在更新的表没有“停机时间”的要求。

    听起来您最初是在读取文件并一次执行 INSERT/UPDATE/DELETE 1 行。比这更高效的方法,不涉及清理表格如下:

    1) 将文件批量加载到新的单独表中(无索引)
    2)然后在上面创建PK
    3) 运行 3 条语句,从这个新(临时)表中更新原始表:
    删除主表中新表中不存在的行
    更新主表中新表中有匹配行的行
    从新表中将不存在的行插入主表

    这将比逐行操作执行得更好,并有望满足您的总体要求

    【讨论】:

    • 谢谢,我要运行一些测试,看看我是想使用它还是只是在短期内将批量插入保持在锁定的事务中。
    【解决方案4】:

    有一种方法可以零停机时间更新表:在表中保留两天的数据,并在加载新行后删除旧行

    1. 添加一个 DataDate 列,表示大约 150K 行的有效日期。
    2. 使用“今天的”DataDate 创建一个单行单列表。
    3. 创建两个表的视图,只选择与 DataDate 表中的行匹配的行。如果您愿意,请对其进行索引。读者现在将参考这个视图,而不是表格。
    4. 批量插入行。 (您显然需要将 DataDate 添加到每一行。)
    5. 更新 DataDate 表。 立即查看更新!
    6. 随意删除昨天的行。

    SELECT 性能不会受到影响;沿着主键将一行连接到 150,000 行应该不会对任何不到 15 年的服务器造成任何问题。

    我经常使用这种技术,并且在处理依赖sp_rename 的进程时也遇到了困难。修改架构的生产过程令人头疼。别。

    【讨论】:

      【解决方案5】:

      对于原始速度,我认为表中有大约 150K 行,我只需删除表,从头开始重新创建它(没有索引),然后重新批量加载。批量加载完成后,创建索引。

      这当然假设有一段时间表为空/不存在是可以接受的,听起来确实可能是这种情况。

      【讨论】:

        猜你喜欢
        • 2013-10-11
        • 2018-11-18
        • 1970-01-01
        • 2011-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-15
        相关资源
        最近更新 更多