【问题标题】:Azure function slow executing a stored procedureAzure 函数执行存储过程很慢
【发布时间】:2018-03-19 06:18:00
【问题描述】:

我正在使用 Azure 函数,如计划作业,使用 cron 计时器。在每天早上的特定时间,它会调用一个存储过程。

该函数现在需要 4 分钟来运行存储过程,而在 SSMS 中运行需要几秒钟。尽管努力成功地提高了存储过程的速度,但这个时间还在增加。

函数没有做任何密集的事情。

using (SqlConnection conn = new SqlConnection(str))
{
    conn.Open();

    using (var cmd = new SqlCommand("Stored Proc Here", conn) { CommandType = CommandType.StoredProcedure, CommandTimeout = 600})
    {
        cmd.Parameters.Add("@Param1", SqlDbType.DateTime2).Value = DateTime.Today.AddDays(-30);
        cmd.Parameters.Add("@Param2", SqlDbType.DateTime2).Value = DateTime.Today;

        var result = cmd.ExecuteNonQuery();
    }
}

我已经检查过,当存储过程运行时,数据库没有被另一个进程加载。

我可以做些什么来加快 Azure 功能?或者有什么方法可以找出它为什么这么慢?

更新。

我不认为 Azure 函数有问题,问题似乎出在 SQL Server 上。

我最终运行了生产 SP 并查看了执行计划。我注意到统计数据出路了,例如一个连接预计返回的行数为 20,但实际数字接近 800k。

我的问题的解决方案是每周更新特定表的统计信息。

关于为什么统计数据如此之多,客户每晚都会进行批量更新并插入数十万行。我只能假设这影响了统计数据并且它是累积的,所以它似乎随着时间的推移变得更糟。

【问题讨论】:

  • 当您在 SSMS 中运行它时,您是否使用 完全 相同的参数值运行它?如果您在 Visual Studio 中本地运行 Azure Function 代码会怎样?
  • 顺便说一句,sproc 在做什么?它是简单地检索数据(在这种情况下您应该使用 View 或 UDF,而不是 sproc)还是执行插入/更新/创建语句?
  • 是的,我使用完全相同的参数值运行它。 sproc 不返回任何数据,它会进行更新。我还没有尝试从 VS 运行它,但会试一试。
  • 启用ApplicationInsights 并在您的函数中添加更多日志记录可能会有所帮助。几个问题:您是否使用计时器触发器?函数完成执行没有任何错误吗?
  • 我正在使用计时器触发器。该函数完成执行而没有错误。我不得不增加 SqlCommand 的超时时间以使存储过程能够完成。我将启用 applicationinsights。

标签: azure azure-sql-database azure-functions


【解决方案1】:

请小心添加重新编译提示。对于给定的简单查询,编译通常比执行要昂贵得多,这意味着使用这种方法可能无法为所有应用程序获得不错的性能。

您的体验有多种可能的原因。这种情况的一个常见原因是您在应用程序与 ssms 路径中有不同的查询计划。这可能由于各种原因而发生(我将在下面总结)。您可以通过使用查询存储(记录有关查询、计划和运行时统计信息的摘要数据)来确定您是否正在获取不同的计划。请在此处查看它的摘要: https://docs.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store?view=sql-server-2017

您需要最近的 ssms 才能获取 ui,但您可以使用来自任何 tds 客户端的直接查询。

现在总结一些可能的原因: 计划差异的一个可能原因是设置选项。这些是查询的不同环境变量,例如启用或禁用 ansi 空值。每个不同的设置都可以改变计划选择,从而改变性能。不幸的是,不同语言驱动程序的默认值不同(每个构建时的历史工件 ​​- 现在很难在不破坏应用程序的情况下进行更改)。您可以查看查询存储以查看是否存在不同的“上下文设置”(设置选项的每个唯一组合都是查询存储中的唯一上下文设置)。每个不同的集合都意味着不同的可能计划,因此潜在的性能变化。

您在帖子中解释的计划更改的第二个主要原因是参数嗅探。根据编译的范围(例如:在 sproc 内与作为 hoc 查询文本),sql 有时会在编译期间查看当前参数值,以推断未来执行中公共值的频率。与忽略该值并仅使用默认频率不同,使用特定值可以生成一个对单个值(或一组值)最佳但对于该组之外的值可能较慢的计划。您也可以在查询存储中的查询计划选择中看到这一点。

除了我提到的之外,还有其他可能导致性能差异的原因。有时在火星模式下运行与不在客户端运行时存在性能差异。您如何称呼影响性能的客户端驱动程序可能会有所不同。

我希望这可以为您提供一些工具来调试造成差异的可能原因。祝你好运!

【讨论】:

    【解决方案2】:

    对于我从事的一个项目,我们遇到了同样的事情。它不是功能问题,而是 sql server 问题。对我们来说,我们在开发过程中更新了存储过程,事实证明,每个执行计划,sql server 将缓存某些路由/索引(外行解释),并且对于新的存储过程不同步。

    我们通过在 sproc 末尾指定 WITH (RECOMPILE) 解决了这个问题,并且 API 调用和 SSMS 具有相同的时序。

    一旦系统安定下来,该声明可以并且应该被删除。

    在慢 sproc fast ssms 等上搜索以找到遇到这种情况的其他人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-10
      • 2018-09-01
      • 1970-01-01
      • 2018-07-17
      • 2018-01-23
      • 2011-09-14
      相关资源
      最近更新 更多