【问题标题】:Slow Batched Deletes On Azure SQL DBAzure SQL DB 上的慢速批量删除
【发布时间】:2019-08-16 12:14:21
【问题描述】:

我有一个应用程序需要删除数据库中所有表中的所有数据。其中一张表包含大约 150k 条记录。我无法截断此表,因为它与其他一些表具有 FK 约束。

在我的机器上针对本地数据库运行时,只需几秒钟即可运行。此时,所有表中的所有数据都被删除,包括 150k 表。本地数据库设置为完全恢复模式。

当我将我的应用程序指向远程 Azure SQL DB 时,性能很差,而且大部分时间都因超时而失败。

我已尝试增加 Azure DB 可用的 DTU,但这似乎没有效果。

我的代码:

using (SqlConnection destinationConnection = new SqlConnection(_myConnectionSting))
{
    destinationConnection.Open();

    foreach (string tableName in importExportTasks.Select(x => x.DestinationTableName))
    {
        string sql = @"
            DECLARE @BatchSize INT
            SET @BatchSize = 5000

            WHILE @BatchSize <> 0
            BEGIN
                DELETE TOP (@BatchSize)
                FROM {0};
                SET @BatchSize = @@rowcount;
            END ";

        string sqlCommand = string.Format(sql, tableName);

        using (SqlCommand cmd = destinationConnection.CreateCommand())
        {
            cmd.CommandText = sqlCommand;
            cmd.CommandTimeout = 240;
            cmd.ExecuteNonQuery();
        }
    }

    success = true;
}

我可以做些什么来提高此代码针对 Azure DB 的性能?我错过了什么?

【问题讨论】:

  • 如果你必须经常这样做 - 创建存储过程,只需将表名作为参数传递。此外,您还想删除所有记录,没有必要分批进行 - “从 1 = 1 的 {0} 中删除”也可以。
  • @VytautasPlečkaitis 我不同意,使用批处理可以最大限度地减少由于日志文件增长、阻塞等造成的中断,尤其是在 Azure 中,您希望尽量减少不必要的 I/O,即使它会自行删除需要更长的时间。但是you have to do it right.
  • @VytautasPlečkaitis 存储过程方法也非常慢。我认为问题在于它是一个 Azure 数据库,而不是方法。
  • @AaronBertrand 我完全同意正确实施的批量删除将是完全有效的方法,但在这种情况下,它会在第一次循环运行时删除 5k,然后全部保留在第二次循环中。
  • @James 我会在查询运行时检查 DTU 使用百分比(或最大百分比),以查看它是否是天蓝色问题 portal.azure.com -> SQL 数据库 -> 选择数据库 - 计算利用率 1 小时。同样关于存储过程 - 它与直接运行查询几乎相同的时间,这样您就不必不断发送完整的 sql 命令(更方便使用)。

标签: c# .net sql-server azure-sql-database


【解决方案1】:

Azure SQL 数据库根据各种指标进行计量。一个主要的(对于这个例子)是日志提交率,它由资源预留的大小决定。您可以在此处阅读有关 vcore 模型的限制:SQL Azure vCore Limits。您应该能够查看资源统计使用情况sys.dm_db_resource_stats 周围的各种 DMV,您还可以使用 Query Store 检查每个查询对资源的具体使用情况,您可以在 DMV 中看到它,但使用 SQL Server Management 更容易导航Studio,因为它有一个漂亮的用户界面。

您很可能只需要更大的资源预留来获得更快的删除性能。如果使用较大的预订量不起作用,请发布我在此处提到的来源的信息,我或其他人可以尝试进一步帮助您。

【讨论】:

  • 这是否也适用于批量插入(bcp 和 .Net 等效项)?
  • 批量插入可能首先会受到日志提交率的限制,是的。如果您在真正提交之前对数据进行处理,那么您通常可以通过首先插入 tempdb 来获得更快的性能(它不会通过网络提交日志,因为它仅对每台机器都是本地的)。超高端的方法可以使用内存中的 OLTP 表作为 ETL 管道中的暂存,并带有 non-durable table 选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2022-08-18
  • 2016-10-02
  • 1970-01-01
  • 2022-07-05
相关资源
最近更新 更多