.NET 应用程序使用的 SQL 视图超时

Posted

技术标签:

【中文标题】.NET 应用程序使用的 SQL 视图超时【英文标题】:SQL View timing out used by .NET Application 【发布时间】:2017-02-22 03:29:40 【问题描述】:

我们有一个 .NET 应用程序,它使用 LINQ to SQL (ORM) 来调用一个视图,该视图包含来自不同数据库中多个对象的连接。 .NET 应用程序调用此视图超时,但我们的 DBA 运行以下语句:

sp_refreshview on the view and the subsequennt sql views

应用程序再次开始运行。

此应用程序在接近 20 分钟后再次在同一视图上开始超时。所以我们的 DBA 已经安排了一个作业,每 30 分钟运行一次上述语句。视图没有发生结构性变化,我们正试图弄清楚为什么 sp_refreshview 修复了这个问题,以及我们可以修复的潜在问题是什么?

【问题讨论】:

视图是否包含任何内联函数?没有.net之类的层直接运行时执行需要多长时间?所以通过管理工作室等...... 视图不包含任何内联函数。当 sp_refresh 完成后,直接通过 .net 或 sql management studio 运行时,查看只需要几毫秒。如果 sp_refresh 没有完成,视图仍然只能在几毫秒内从 sql server 运行,但从 .net 运行时会超时 @user1490835,您的最后一条评论听起来与我刚才在回答中指出的 Erland Sommarskog 的文章 Slow in the Application, Fast in SSMS 的标题完全相同。您是否阅读并检查过该问题与该文章中讨论的问题是否不同? @VladimirBaranov,我确实看过这篇文章,其中没有我们不知道或尝试过的内容。我也把它交给了我们的 DBA,但那里没有任何积极的反馈。但是无论如何我都会奖励你赏金,因为这似乎是最有用的答案(每个答案/评论都很有用)但由于问题仍然存在,我不会将其标记为答案。 谢谢@user1490835。不幸的是,我没有任何其他想法。我会尝试确认是否有两种不同的执行计划——“慢”和“快”。如果是,那么看看你能做些什么来防止服务器生成“慢”计划。如果应用程序和 SSMS 的计划相同,则检查应用程序以找出有时查询缓慢的原因。 【参考方案1】:

sp_refreshview 解决问题的原因是视图不受模式限制。 SQLServer 保留有关视图的元数据以帮助执行,并且由于视图不受模式绑定,因此元数据会随着基础对象的更新而过时(想想 DML 语句)。 sp_refreshview 所做的是更新非模式绑定视图的元数据,以便它们能够以最佳方式运行。看看documentation 的sp_refreshview

要弄清楚为什么会这样,请考虑一下什么是视图?视图只是一个查询。存储的元数据与该查询相关。

每当您运行查询时,服务器都会找出运行该查询的最佳方式(称为计划),这取决于查询中使用的表的统计信息。随着表中的数据发生变化,表的统计信息也会发生变化,因此计划也会发生变化。当您创建视图(非模式绑定)时,将存储围绕最佳执行的元数据(很可能是计划)。由于视图只是一个查询,因此计划可能会过时,sp_refreshview 会更新该元数据。

【讨论】:

好的,但问题是视图内部没有更新。过去2年的观点是一样的。没有 DML 声明...没有任何与视图相关的内容被触及。在发布此问题之前,我们确实查看了文档,目前除了它正在工作之外没有什么意义 构成视图的基础数据在 2 年内没有变化?视图本身并没有发生变化,而是表中的数据构成了将要发生变化的视图。 但这将如何改变视图周围的元数据? 问题是如果我们更新统计信息并忽略视图刷新(sp_refreshview)仍然超时如果你说的是正确的,那么更新统计信息肯定会优化执行计划从而调整视图......但是那不是这样的 如果你想要修复,你需要架构绑定你的视图。否则,您将需要定期运行 sp_refreshview 以获得最佳性能。【参考方案2】:

很可能sp_refreshview 导致服务器从缓存中删除缓存的查询执行计划。当您在调用sp_refreshview 后运行查询时,会生成新的(更好的)执行计划。这就是为什么调用sp_refreshview 会有所帮助。显然,更新统计信息不会删除缓存的执行计划,这就是为什么它对您的情况没有帮助。

有些类型的查询无法为所有可能的参数值制定一个好的计划,或者您的数据可能会严重倾斜。

如果您将OPTION(RECOMPILE) 添加到您的查询中,您很可能不需要调用sp_refreshview 来使其快速运行。

当你的 ORM 生成查询时,我不知道如何添加这个查询提示。

我建议您阅读 Erland Sommarskog 的一篇出色的文章 Slow in the Application, Fast in SSMS。

【讨论】:

它不工作。还有其他建议吗?有没有办法在 sp_Refreshview 存储过程中获取 sql? @user1490835,我会尝试使用 SQL Profiler 查看sp_refreshview 运行时执行了哪些查询。 根据我在 Google 上的了解和阅读以及与我们的 DBA 聊天后,SQL Server 似乎没有为视图创建查询计划。 @user1490835,当然,它不会为视图创建执行计划。它为通过视图访问表的实际查询创建执行计划。我的猜测是,在您的情况下,这些执行计划在 20 分钟后变得非最优。 sp_refreshview 将导致服务器删除为使用视图进行查询而构建的所有缓存计划。您应该能够通过不首先使用OPTION(RECOMPILE) 缓存计划来实现相同的效果。 ... @user1490835,另一方面,如果您说OPTION(RECOMPILE) 对您没有帮助,那么我猜sp_refreshview 导致服务器删除缓存的计划是错误的。或者问题与非最优计划无关。为了确认,我会尝试在查询快速运行时获取执行计划,然后在相同查询在 20 分钟内运行缓慢时获取执行计划并进行比较。【参考方案3】:

元数据是关于视图使用的表的信息。统计信息更新有关数据的信息。查看您的视图定义可能会有所帮助。例如,在视图中有一个 select * 可能真的会给你带来问题。作为复习,视图只是一个语句,直到它被执行。如果您使用的表总是在更改其结构或被删除并重新添加,则每次都需要运行 sp_refreshview。如果您需要其他帮助,您将需要提供查询和有关基础表的任何信息,例如处理刷新它们。上述所有 cmets 都在合理范围内正确。

【讨论】:

以上是关于.NET 应用程序使用的 SQL 视图超时的主要内容,如果未能解决你的问题,请参考以下文章

如何调查 ASP.net 应用程序上的 SQL Server 超时错误?

ASP.NET Core SQL 连接超时

Sql Server Profiler 跟踪在 Web 应用程序中给出超时

使用 SQL Azure 从会话状态提供程序(实体框架)持续接收“超时时间已过”

SQL 过程超时

在 SQL Server 2008 中执行视图时出现“超时已过期”错误